Merge branch 'master' of github.com:google/grpc

pull/145/head
murgatroid99 10 years ago
commit e1613dcd31
  1. 12
      .clang-format
  2. 14
      .gitignore
  3. 2920
      Makefile
  4. 1024
      build.json
  5. 5
      include/grpc/grpc.h
  6. 3
      src/core/channel/channel_stack.c
  7. 2
      src/core/channel/child_channel.h
  8. 68
      src/core/iomgr/pollset_kick.h
  9. 161
      src/core/iomgr/pollset_kick_posix.c
  10. 47
      src/core/iomgr/pollset_kick_posix.h
  11. 9
      src/core/iomgr/pollset_multipoller_with_poll_posix.c
  12. 84
      src/core/iomgr/pollset_posix.c
  13. 3
      src/core/iomgr/pollset_posix.h
  14. 5
      src/core/security/auth.c
  15. 8
      src/core/security/security_context.c
  16. 3
      src/core/statistics/census_rpc_stats.c
  17. 3
      src/core/statistics/census_tracing.c
  18. 7
      src/core/surface/completion_queue.c
  19. 2
      src/core/surface/completion_queue.h
  20. 3
      src/core/surface/event_string.c
  21. 25
      src/core/surface/server.c
  22. 9
      src/core/transport/chttp2_transport.c
  23. 13
      src/core/tsi/fake_transport_security.c
  24. 21
      src/core/tsi/ssl_transport_security.c
  25. 3
      src/core/tsi/ssl_transport_security.h
  26. 4
      src/cpp/server/completion_queue.cc
  27. 4
      src/cpp/stream/stream_context.h
  28. 3
      src/php/.gitignore
  29. 16
      src/php/bin/run_tests.sh
  30. 15
      src/php/ext/grpc/call.c
  31. 12
      src/php/ext/grpc/completion_queue.c
  32. 17
      src/php/ext/grpc/config.m4
  33. 7
      src/php/ext/grpc/credentials.c
  34. 3
      src/php/ext/grpc/php_grpc.c
  35. 14
      src/php/ext/grpc/timeval.c
  36. 10
      src/ruby/.rubocop.yml
  37. 52
      src/ruby/.rubocop_todo.yml
  38. 32
      src/ruby/Rakefile
  39. 53
      src/ruby/bin/interop/interop_client.rb
  40. 35
      src/ruby/bin/interop/interop_server.rb
  41. 25
      src/ruby/bin/math_client.rb
  42. 42
      src/ruby/bin/math_server.rb
  43. 12
      src/ruby/bin/noproto_client.rb
  44. 16
      src/ruby/bin/noproto_server.rb
  45. 6
      src/ruby/ext/grpc/extconf.rb
  46. 25
      src/ruby/grpc.gemspec
  47. 9
      src/ruby/lib/grpc/beefcake.rb
  48. 7
      src/ruby/lib/grpc/core/event.rb
  49. 14
      src/ruby/lib/grpc/core/time_consts.rb
  50. 7
      src/ruby/lib/grpc/errors.rb
  51. 97
      src/ruby/lib/grpc/generic/active_call.rb
  52. 33
      src/ruby/lib/grpc/generic/bidi_call.rb
  53. 60
      src/ruby/lib/grpc/generic/client_stub.rb
  54. 43
      src/ruby/lib/grpc/generic/rpc_desc.rb
  55. 106
      src/ruby/lib/grpc/generic/rpc_server.rb
  56. 58
      src/ruby/lib/grpc/generic/service.rb
  57. 1
      src/ruby/lib/grpc/version.rb
  58. 2
      src/ruby/spec/alloc_spec.rb
  59. 4
      src/ruby/spec/byte_buffer_spec.rb
  60. 40
      src/ruby/spec/call_spec.rb
  61. 35
      src/ruby/spec/channel_spec.rb
  62. 74
      src/ruby/spec/client_server_spec.rb
  63. 5
      src/ruby/spec/completion_queue_spec.rb
  64. 14
      src/ruby/spec/credentials_spec.rb
  65. 22
      src/ruby/spec/event_spec.rb
  66. 48
      src/ruby/spec/generic/active_call_spec.rb
  67. 127
      src/ruby/spec/generic/client_stub_spec.rb
  68. 117
      src/ruby/spec/generic/rpc_desc_spec.rb
  69. 35
      src/ruby/spec/generic/rpc_server_pool_spec.rb
  70. 139
      src/ruby/spec/generic/rpc_server_spec.rb
  71. 58
      src/ruby/spec/generic/service_spec.rb
  72. 2
      src/ruby/spec/metadata_spec.rb
  73. 4
      src/ruby/spec/port_picker.rb
  74. 13
      src/ruby/spec/server_credentials_spec.rb
  75. 48
      src/ruby/spec/server_spec.rb
  76. 4
      src/ruby/spec/time_consts_spec.rb
  77. 82
      templates/Makefile.template
  78. 9
      templates/tools/run_tests/tests.json.template
  79. 2
      templates/vsprojects/vs2013/grpc.sln.template
  80. 7
      test/build/perftools.c
  81. 8
      test/core/end2end/cq_verifier.c
  82. 1
      test/core/end2end/cq_verifier.h
  83. 5
      test/core/end2end/gen_build_json.py
  84. 160
      test/core/end2end/tests/graceful_server_shutdown.c
  85. 11
      test/core/fling/server.c
  86. 101
      test/core/iomgr/poll_kick_test.c
  87. 18
      test/core/statistics/hash_table_test.c
  88. 4
      test/core/surface/completion_queue_benchmark.c
  89. 4
      test/core/surface/completion_queue_test.c
  90. 18
      test/core/util/grpc_profiler.c
  91. 63
      tools/buildgen/build-cleaner.py
  92. 4
      tools/buildgen/generate_projects.sh
  93. 5
      tools/clang-format/clang-format-all.sh
  94. 11
      tools/clang-format/config.sh
  95. 21
      tools/run_tests/build_php.sh
  96. 104
      tools/run_tests/run_tests.py
  97. 805
      tools/run_tests/tests.json
  98. 32
      vsprojects/vs2013/build_and_run_tests.bat
  99. 14
      vsprojects/vs2013/gpr.vcxproj
  100. 24
      vsprojects/vs2013/grpc.sln
  101. Some files were not shown because too many files have changed in this diff Show More

@ -2,27 +2,22 @@
Language: Cpp Language: Cpp
# BasedOnStyle: Google # BasedOnStyle: Google
AccessModifierOffset: -1 AccessModifierOffset: -1
AlignAfterOpenBracket: true ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: true AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true AllowShortLoopsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All AllowShortFunctionsOnASingleLine: All
AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakTemplateDeclarations: true AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: true AlwaysBreakBeforeMultilineStrings: true
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false BreakConstructorInitializersBeforeComma: false
BinPackParameters: true BinPackParameters: true
BinPackArguments: true
ColumnLimit: 80 ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
DerivePointerAlignment: true DerivePointerAlignment: true
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true IndentCaseLabels: true
@ -31,7 +26,6 @@ IndentFunctionDeclarationAfterType: false
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: false KeepEmptyLinesAtTheStartOfBlocks: false
NamespaceIndentation: None NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakBeforeFirstCallParameter: 1
@ -49,11 +43,9 @@ TabWidth: 8
UseTab: Never UseTab: Never
BreakBeforeBraces: Attach BreakBeforeBraces: Attach
SpacesInParentheses: false SpacesInParentheses: false
SpacesInSquareBrackets: false
SpacesInAngles: false SpacesInAngles: false
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false SpacesInCStyleCastParentheses: false
SpaceAfterCStyleCast: false
SpacesInContainerLiterals: true SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4

14
.gitignore vendored

@ -1,11 +1,19 @@
# C/C++ build outputs
bins bins
coverage
deps
*.gcno
gens gens
libs libs
objs objs
# gcov coverage data
coverage
*.gcno
# profiler output
*.prof
# python compiled objects
*.pyc *.pyc
# cache for run_tests.py # cache for run_tests.py
.run_tests_cache .run_tests_cache

2920
Makefile

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

@ -194,6 +194,7 @@ typedef enum grpc_completion_type {
GRPC_FINISHED, /* An RPC has finished. The event contains status. GRPC_FINISHED, /* An RPC has finished. The event contains status.
On the server this will be OK or Cancelled. */ On the server this will be OK or Cancelled. */
GRPC_SERVER_RPC_NEW, /* A new RPC has arrived at the server */ GRPC_SERVER_RPC_NEW, /* A new RPC has arrived at the server */
GRPC_SERVER_SHUTDOWN, /* The server has finished shutting down */
GRPC_COMPLETION_DO_NOT_USE /* must be last, forces users to include GRPC_COMPLETION_DO_NOT_USE /* must be last, forces users to include
a default: case */ a default: case */
} grpc_completion_type; } grpc_completion_type;
@ -439,6 +440,10 @@ void grpc_server_start(grpc_server *server);
Existing calls will be allowed to complete. */ Existing calls will be allowed to complete. */
void grpc_server_shutdown(grpc_server *server); void grpc_server_shutdown(grpc_server *server);
/* As per grpc_server_shutdown, but send a GRPC_SERVER_SHUTDOWN event when
there are no more calls being serviced. */
void grpc_server_shutdown_and_notify(grpc_server *server, void *tag);
/* Destroy a server. /* Destroy a server.
Forcefully cancels all existing calls. */ Forcefully cancels all existing calls. */
void grpc_server_destroy(grpc_server *server); void grpc_server_destroy(grpc_server *server);

@ -190,7 +190,8 @@ void grpc_channel_next_op(grpc_channel_element *elem, grpc_channel_op *op) {
grpc_channel_stack *grpc_channel_stack_from_top_element( grpc_channel_stack *grpc_channel_stack_from_top_element(
grpc_channel_element *elem) { grpc_channel_element *elem) {
return (grpc_channel_stack *)((char *)(elem)-ROUND_UP_TO_ALIGNMENT_SIZE( return (grpc_channel_stack *)((char *)(elem) -
ROUND_UP_TO_ALIGNMENT_SIZE(
sizeof(grpc_channel_stack))); sizeof(grpc_channel_stack)));
} }

@ -39,7 +39,7 @@
/* helper for filters that need to host child channel stacks... handles /* helper for filters that need to host child channel stacks... handles
lifetime and upwards propagation cleanly */ lifetime and upwards propagation cleanly */
const grpc_channel_filter grpc_child_channel_top_filter; extern const grpc_channel_filter grpc_child_channel_top_filter;
typedef grpc_channel_stack grpc_child_channel; typedef grpc_channel_stack grpc_child_channel;
typedef grpc_call_stack grpc_child_call; typedef grpc_call_stack grpc_child_call;

@ -0,0 +1,68 @@
/*
*
* 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.
*
*/
#ifndef __GRPC_INTERNAL_IOMGR_POLLSET_KICK_H_
#define __GRPC_INTERNAL_IOMGR_POLLSET_KICK_H_
#include <grpc/support/port_platform.h>
/* This is an abstraction around the typical pipe mechanism for waking up a
thread sitting in a poll() style call. */
#ifdef GPR_POSIX_SOCKET
#include "src/core/iomgr/pollset_kick_posix.h"
#else
#error "No pollset kick support on platform"
#endif
void grpc_pollset_kick_global_init(void);
void grpc_pollset_kick_global_destroy(void);
void grpc_pollset_kick_init(grpc_pollset_kick_state *kick_state);
void grpc_pollset_kick_destroy(grpc_pollset_kick_state *kick_state);
/* Must be called before entering poll(). If return value is -1, this consumed
an existing kick. Otherwise the return value is an FD to add to the poll set.
*/
int grpc_pollset_kick_pre_poll(grpc_pollset_kick_state *kick_state);
/* Consume an existing kick. Must be called after poll returns that the fd was
readable, and before calling kick_post_poll. */
void grpc_pollset_kick_consume(grpc_pollset_kick_state *kick_state);
/* Must be called after pre_poll, and after consume if applicable */
void grpc_pollset_kick_post_poll(grpc_pollset_kick_state *kick_state);
void grpc_pollset_kick_kick(grpc_pollset_kick_state *kick_state);
#endif /* __GRPC_INTERNAL_IOMGR_POLLSET_KICK_H_ */

@ -0,0 +1,161 @@
/*
*
* 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.
*
*/
#include "src/core/iomgr/pollset_kick_posix.h"
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "src/core/iomgr/socket_utils_posix.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
/* This implementation is based on a freelist of pipes. */
typedef struct grpc_kick_pipe_info {
int pipe_read_fd;
int pipe_write_fd;
struct grpc_kick_pipe_info *next;
} grpc_kick_pipe_info;
static grpc_kick_pipe_info *pipe_freelist = NULL;
static gpr_mu pipe_freelist_mu;
static grpc_kick_pipe_info *allocate_pipe() {
grpc_kick_pipe_info *info;
gpr_mu_lock(&pipe_freelist_mu);
if (pipe_freelist != NULL) {
info = pipe_freelist;
pipe_freelist = pipe_freelist->next;
} else {
int pipefd[2];
/* TODO(klempner): Make this nonfatal */
GPR_ASSERT(0 == pipe(pipefd));
GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[0], 1));
GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[1], 1));
info = gpr_malloc(sizeof(*info));
info->pipe_read_fd = pipefd[0];
info->pipe_write_fd = pipefd[1];
info->next = NULL;
}
gpr_mu_unlock(&pipe_freelist_mu);
return info;
}
static void free_pipe(grpc_kick_pipe_info *pipe_info) {
/* TODO(klempner): Start closing pipes if the free list gets too large */
gpr_mu_lock(&pipe_freelist_mu);
pipe_info->next = pipe_freelist;
pipe_freelist = pipe_info;
gpr_mu_unlock(&pipe_freelist_mu);
}
void grpc_pollset_kick_global_init() {
pipe_freelist = NULL;
gpr_mu_init(&pipe_freelist_mu);
}
void grpc_pollset_kick_global_destroy() {
while (pipe_freelist != NULL) {
grpc_kick_pipe_info *current = pipe_freelist;
pipe_freelist = pipe_freelist->next;
close(current->pipe_read_fd);
close(current->pipe_write_fd);
gpr_free(current);
}
gpr_mu_destroy(&pipe_freelist_mu);
}
void grpc_pollset_kick_init(grpc_pollset_kick_state *kick_state) {
gpr_mu_init(&kick_state->mu);
kick_state->kicked = 0;
kick_state->pipe_info = NULL;
}
void grpc_pollset_kick_destroy(grpc_pollset_kick_state *kick_state) {
gpr_mu_destroy(&kick_state->mu);
GPR_ASSERT(kick_state->pipe_info == NULL);
}
int grpc_pollset_kick_pre_poll(grpc_pollset_kick_state *kick_state) {
gpr_mu_lock(&kick_state->mu);
if (kick_state->kicked) {
kick_state->kicked = 0;
gpr_mu_unlock(&kick_state->mu);
return -1;
}
kick_state->pipe_info = allocate_pipe();
gpr_mu_unlock(&kick_state->mu);
return kick_state->pipe_info->pipe_read_fd;
}
void grpc_pollset_kick_consume(grpc_pollset_kick_state *kick_state) {
char buf[128];
int r;
for (;;) {
r = read(kick_state->pipe_info->pipe_read_fd, buf, sizeof(buf));
if (r > 0) continue;
if (r == 0) return;
switch (errno) {
case EAGAIN:
return;
case EINTR:
continue;
default:
gpr_log(GPR_ERROR, "error reading pipe: %s", strerror(errno));
return;
}
}
}
void grpc_pollset_kick_post_poll(grpc_pollset_kick_state *kick_state) {
gpr_mu_lock(&kick_state->mu);
free_pipe(kick_state->pipe_info);
kick_state->pipe_info = NULL;
gpr_mu_unlock(&kick_state->mu);
}
void grpc_pollset_kick_kick(grpc_pollset_kick_state *kick_state) {
gpr_mu_lock(&kick_state->mu);
if (kick_state->pipe_info != NULL) {
char c = 0;
while (write(kick_state->pipe_info->pipe_write_fd, &c, 1) != 1 &&
errno == EINTR)
;
} else {
kick_state->kicked = 1;
}
gpr_mu_unlock(&kick_state->mu);
}

@ -0,0 +1,47 @@
/*
*
* 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.
*
*/
#ifndef __GRPC_INTERNAL_IOMGR_POLLSET_KICK_POSIX_H_
#define __GRPC_INTERNAL_IOMGR_POLLSET_KICK_POSIX_H_
#include <grpc/support/sync.h>
struct grpc_kick_pipe_info;
typedef struct grpc_pollset_kick_state {
gpr_mu mu;
int kicked;
struct grpc_kick_pipe_info *pipe_info;
} grpc_pollset_kick_state;
#endif /* __GRPC_INTERNAL_IOMGR_POLLSET_KICK_POSIX_H_ */

@ -131,7 +131,11 @@ static int multipoll_with_poll_pollset_maybe_work(
} }
nf = 0; nf = 0;
np = 1; np = 1;
h->pfds[0].fd = grpc_kick_read_fd(pollset); h->pfds[0].fd = grpc_pollset_kick_pre_poll(&pollset->kick_state);
if (h->pfds[0].fd < 0) {
/* Already kicked */
return 1;
}
h->pfds[0].events = POLLIN; h->pfds[0].events = POLLIN;
h->pfds[0].revents = POLLOUT; h->pfds[0].revents = POLLOUT;
for (i = 0; i < h->fd_count; i++) { for (i = 0; i < h->fd_count; i++) {
@ -173,7 +177,7 @@ static int multipoll_with_poll_pollset_maybe_work(
/* do nothing */ /* do nothing */
} else { } else {
if (h->pfds[0].revents & POLLIN) { if (h->pfds[0].revents & POLLIN) {
grpc_kick_drain(pollset); grpc_pollset_kick_consume(&pollset->kick_state);
} }
for (i = 1; i < np; i++) { for (i = 1; i < np; i++) {
if (h->pfds[i].revents & POLLIN) { if (h->pfds[i].revents & POLLIN) {
@ -184,6 +188,7 @@ static int multipoll_with_poll_pollset_maybe_work(
} }
} }
} }
grpc_pollset_kick_post_poll(&pollset->kick_state);
end_polling(pollset); end_polling(pollset);
gpr_mu_lock(&pollset->mu); gpr_mu_lock(&pollset->mu);

@ -48,18 +48,6 @@
#include <grpc/support/thd.h> #include <grpc/support/thd.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
/* kick pipes: we keep a sharded set of pipes to allow breaking from poll.
Ideally this would be 1:1 with pollsets, but we'd like to avoid associating
full kernel objects with each pollset to keep them lightweight, so instead
keep a sharded set and allow associating a pollset with one of the shards.
TODO(ctiller): move this out from this file, and allow an eventfd
implementation on linux */
#define LOG2_KICK_SHARDS 6
#define KICK_SHARDS (1 << LOG2_KICK_SHARDS)
static int g_kick_pipes[KICK_SHARDS][2];
static grpc_pollset g_backup_pollset; static grpc_pollset g_backup_pollset;
static int g_shutdown_backup_poller; static int g_shutdown_backup_poller;
static gpr_event g_backup_poller_done; static gpr_event g_backup_poller_done;
@ -82,65 +70,22 @@ static void backup_poller(void *p) {
gpr_event_set(&g_backup_poller_done, (void *)1); gpr_event_set(&g_backup_poller_done, (void *)1);
} }
static size_t kick_shard(const grpc_pollset *info) {
size_t x = (size_t)info;
return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (KICK_SHARDS - 1);
}
int grpc_kick_read_fd(grpc_pollset *p) {
return g_kick_pipes[kick_shard(p)][0];
}
static int grpc_kick_write_fd(grpc_pollset *p) {
return g_kick_pipes[kick_shard(p)][1];
}
void grpc_pollset_force_kick(grpc_pollset *p) {
char c = 0;
while (write(grpc_kick_write_fd(p), &c, 1) != 1 && errno == EINTR)
;
}
void grpc_pollset_kick(grpc_pollset *p) { void grpc_pollset_kick(grpc_pollset *p) {
if (!p->counter) return; if (!p->counter) return;
grpc_pollset_force_kick(p); grpc_pollset_kick_kick(&p->kick_state);
} }
void grpc_kick_drain(grpc_pollset *p) { void grpc_pollset_force_kick(grpc_pollset *p) { grpc_pollset_kick(p); }
int fd = grpc_kick_read_fd(p);
char buf[128];
int r;
for (;;) {
r = read(fd, buf, sizeof(buf));
if (r > 0) continue;
if (r == 0) return;
switch (errno) {
case EAGAIN:
return;
case EINTR:
continue;
default:
gpr_log(GPR_ERROR, "error reading pipe: %s", strerror(errno));
return;
}
}
}
/* global state management */ /* global state management */
grpc_pollset *grpc_backup_pollset(void) { return &g_backup_pollset; } grpc_pollset *grpc_backup_pollset(void) { return &g_backup_pollset; }
void grpc_pollset_global_init(void) { void grpc_pollset_global_init(void) {
int i;
gpr_thd_id id; gpr_thd_id id;
/* initialize the kick shards */ /* Initialize kick fd state */
for (i = 0; i < KICK_SHARDS; i++) { grpc_pollset_kick_global_init();
GPR_ASSERT(0 == pipe(g_kick_pipes[i]));
GPR_ASSERT(grpc_set_socket_nonblocking(g_kick_pipes[i][0], 1));
GPR_ASSERT(grpc_set_socket_nonblocking(g_kick_pipes[i][1], 1));
}
/* initialize the backup pollset */ /* initialize the backup pollset */
grpc_pollset_init(&g_backup_pollset); grpc_pollset_init(&g_backup_pollset);
@ -152,8 +97,6 @@ void grpc_pollset_global_init(void) {
} }
void grpc_pollset_global_shutdown(void) { void grpc_pollset_global_shutdown(void) {
int i;
/* terminate the backup poller thread */ /* terminate the backup poller thread */
gpr_mu_lock(&g_backup_pollset.mu); gpr_mu_lock(&g_backup_pollset.mu);
g_shutdown_backup_poller = 1; g_shutdown_backup_poller = 1;
@ -163,11 +106,8 @@ void grpc_pollset_global_shutdown(void) {
/* destroy the backup pollset */ /* destroy the backup pollset */
grpc_pollset_destroy(&g_backup_pollset); grpc_pollset_destroy(&g_backup_pollset);
/* destroy the kick shards */ /* destroy the kick pipes */
for (i = 0; i < KICK_SHARDS; i++) { grpc_pollset_kick_global_destroy();
close(g_kick_pipes[i][0]);
close(g_kick_pipes[i][1]);
}
} }
/* main interface */ /* main interface */
@ -178,6 +118,7 @@ static void become_unary_pollset(grpc_pollset *pollset, grpc_fd *fd);
void grpc_pollset_init(grpc_pollset *pollset) { void grpc_pollset_init(grpc_pollset *pollset) {
gpr_mu_init(&pollset->mu); gpr_mu_init(&pollset->mu);
gpr_cv_init(&pollset->cv); gpr_cv_init(&pollset->cv);
grpc_pollset_kick_init(&pollset->kick_state);
become_empty_pollset(pollset); become_empty_pollset(pollset);
} }
@ -213,6 +154,7 @@ int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
void grpc_pollset_destroy(grpc_pollset *pollset) { void grpc_pollset_destroy(grpc_pollset *pollset) {
pollset->vtable->destroy(pollset); pollset->vtable->destroy(pollset);
grpc_pollset_kick_destroy(&pollset->kick_state);
gpr_mu_destroy(&pollset->mu); gpr_mu_destroy(&pollset->mu);
gpr_cv_destroy(&pollset->cv); gpr_cv_destroy(&pollset->cv);
} }
@ -290,7 +232,11 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset,
return 1; return 1;
} }
} }
pfd[0].fd = grpc_kick_read_fd(pollset); pfd[0].fd = grpc_pollset_kick_pre_poll(&pollset->kick_state);
if (pfd[0].fd < 0) {
/* Already kicked */
return 1;
}
pfd[0].events = POLLIN; pfd[0].events = POLLIN;
pfd[0].revents = 0; pfd[0].revents = 0;
pfd[1].fd = fd->fd; pfd[1].fd = fd->fd;
@ -308,7 +254,7 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset,
/* do nothing */ /* do nothing */
} else { } else {
if (pfd[0].revents & POLLIN) { if (pfd[0].revents & POLLIN) {
grpc_kick_drain(pollset); grpc_pollset_kick_consume(&pollset->kick_state);
} }
if (pfd[1].revents & POLLIN) { if (pfd[1].revents & POLLIN) {
grpc_fd_become_readable(fd, allow_synchronous_callback); grpc_fd_become_readable(fd, allow_synchronous_callback);
@ -318,6 +264,8 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset,
} }
} }
grpc_pollset_kick_post_poll(&pollset->kick_state);
gpr_mu_lock(&pollset->mu); gpr_mu_lock(&pollset->mu);
grpc_fd_end_poll(fd, pollset); grpc_fd_end_poll(fd, pollset);
pollset->counter = 0; pollset->counter = 0;

@ -36,6 +36,8 @@
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include "src/core/iomgr/pollset_kick.h"
typedef struct grpc_pollset_vtable grpc_pollset_vtable; typedef struct grpc_pollset_vtable grpc_pollset_vtable;
/* forward declare only in this file to avoid leaking impl details via /* forward declare only in this file to avoid leaking impl details via
@ -51,6 +53,7 @@ typedef struct grpc_pollset {
const grpc_pollset_vtable *vtable; const grpc_pollset_vtable *vtable;
gpr_mu mu; gpr_mu mu;
gpr_cv cv; gpr_cv cv;
grpc_pollset_kick_state kick_state;
int counter; int counter;
union { union {
int fd; int fd;

@ -157,5 +157,6 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
} }
const grpc_channel_filter grpc_client_auth_filter = { const grpc_channel_filter grpc_client_auth_filter = {
call_op, channel_op, sizeof(call_data), init_call_elem, destroy_call_elem, call_op, channel_op, sizeof(call_data),
sizeof(channel_data), init_channel_elem, destroy_channel_elem, "auth"}; init_call_elem, destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem, "auth"};

@ -413,10 +413,10 @@ grpc_security_status grpc_ssl_server_security_context_create(
(const unsigned char **)&config->pem_private_key, (const unsigned char **)&config->pem_private_key,
&config->pem_private_key_size, &config->pem_private_key_size,
(const unsigned char **)&config->pem_cert_chain, (const unsigned char **)&config->pem_cert_chain,
&config->pem_cert_chain_size, 1, &config->pem_cert_chain_size, 1, config->pem_root_certs,
config->pem_root_certs, config->pem_root_certs_size, config->pem_root_certs_size, GRPC_SSL_CIPHER_SUITES,
GRPC_SSL_CIPHER_SUITES, alpn_protocol_strings, alpn_protocol_strings, alpn_protocol_string_lengths, num_alpn_protocols,
alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory); &c->handshaker_factory);
if (result != TSI_OK) { if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
tsi_result_to_string(result)); tsi_result_to_string(result));

@ -86,7 +86,8 @@ static void delete_key(void* key) { gpr_free(key); }
static const census_ht_option ht_opt = { static const census_ht_option ht_opt = {
CENSUS_HT_POINTER /* key type */, 1999 /* n_of_buckets */, CENSUS_HT_POINTER /* key type */, 1999 /* n_of_buckets */,
simple_hash /* hash function */, cmp_str_keys /* key comparator */, simple_hash /* hash function */, cmp_str_keys /* key comparator */,
delete_stats /* data deleter */, delete_key /* key deleter */}; delete_stats /* data deleter */, delete_key /* key deleter */
};
static void init_rpc_stats(void* stats) { static void init_rpc_stats(void* stats) {
memset(stats, 0, sizeof(census_rpc_stats)); memset(stats, 0, sizeof(census_rpc_stats));

@ -76,7 +76,8 @@ static void delete_trace_obj(void* obj) { trace_obj_destroy((trace_obj*)obj); }
static const census_ht_option ht_opt = { static const census_ht_option ht_opt = {
CENSUS_HT_UINT64 /* key type*/, 571 /* n_of_buckets */, NULL /* hash */, CENSUS_HT_UINT64 /* key type*/, 571 /* n_of_buckets */, NULL /* hash */,
NULL /* compare_keys */, delete_trace_obj /* delete data */, NULL /* compare_keys */, delete_trace_obj /* delete data */,
NULL /* delete key */}; NULL /* delete key */
};
static gpr_once g_init_mutex_once = GPR_ONCE_INIT; static gpr_once g_init_mutex_once = GPR_ONCE_INIT;
static gpr_mu g_mu; /* Guards following two static variables. */ static gpr_mu g_mu; /* Guards following two static variables. */

@ -155,6 +155,13 @@ static void end_op_locked(grpc_completion_queue *cc,
} }
} }
void grpc_cq_end_server_shutdown(grpc_completion_queue *cc, void *tag) {
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
add_locked(cc, GRPC_SERVER_SHUTDOWN, tag, NULL, NULL, NULL);
end_op_locked(cc, GRPC_SERVER_SHUTDOWN);
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
}
void grpc_cq_end_read(grpc_completion_queue *cc, void *tag, grpc_call *call, void grpc_cq_end_read(grpc_completion_queue *cc, void *tag, grpc_call *call,
grpc_event_finish_func on_finish, void *user_data, grpc_event_finish_func on_finish, void *user_data,
grpc_byte_buffer *read) { grpc_byte_buffer *read) {

@ -97,6 +97,8 @@ void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call,
gpr_timespec deadline, size_t metadata_count, gpr_timespec deadline, size_t metadata_count,
grpc_metadata *metadata_elements); grpc_metadata *metadata_elements);
void grpc_cq_end_server_shutdown(grpc_completion_queue *cc, void *tag);
/* disable polling for some tests */ /* disable polling for some tests */
void grpc_completion_queue_dont_poll_test_only(grpc_completion_queue *cc); void grpc_completion_queue_dont_poll_test_only(grpc_completion_queue *cc);

@ -63,6 +63,9 @@ char *grpc_event_string(grpc_event *ev) {
if (ev == NULL) return gpr_strdup("null"); if (ev == NULL) return gpr_strdup("null");
switch (ev->type) { switch (ev->type) {
case GRPC_SERVER_SHUTDOWN:
p += sprintf(p, "SERVER_SHUTDOWN");
break;
case GRPC_QUEUE_SHUTDOWN: case GRPC_QUEUE_SHUTDOWN:
p += sprintf(p, "QUEUE_SHUTDOWN"); p += sprintf(p, "QUEUE_SHUTDOWN");
break; break;

@ -81,6 +81,8 @@ struct grpc_server {
size_t tag_cap; size_t tag_cap;
gpr_uint8 shutdown; gpr_uint8 shutdown;
gpr_uint8 have_shutdown_tag;
void *shutdown_tag;
call_data *lists[CALL_LIST_COUNT]; call_data *lists[CALL_LIST_COUNT];
channel_data root_channel_data; channel_data root_channel_data;
@ -375,6 +377,10 @@ static void destroy_call_elem(grpc_call_element *elem) {
for (i = 0; i < CALL_LIST_COUNT; i++) { for (i = 0; i < CALL_LIST_COUNT; i++) {
call_list_remove(chand->server, elem->call_data, i); call_list_remove(chand->server, elem->call_data, i);
} }
if (chand->server->shutdown && chand->server->have_shutdown_tag &&
chand->server->lists[ALL_CALLS] == NULL) {
grpc_cq_end_server_shutdown(chand->server->cq, chand->server->shutdown_tag);
}
gpr_mu_unlock(&chand->server->mu); gpr_mu_unlock(&chand->server->mu);
server_unref(chand->server); server_unref(chand->server);
@ -513,7 +519,8 @@ grpc_transport_setup_result grpc_server_setup_transport(
grpc_channel_get_channel_stack(channel), transport); grpc_channel_get_channel_stack(channel), transport);
} }
void grpc_server_shutdown(grpc_server *server) { void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
void *shutdown_tag) {
listener *l; listener *l;
void **tags; void **tags;
size_t ntags; size_t ntags;
@ -551,6 +558,14 @@ void grpc_server_shutdown(grpc_server *server) {
server->ntags = 0; server->ntags = 0;
server->shutdown = 1; server->shutdown = 1;
server->have_shutdown_tag = have_shutdown_tag;
server->shutdown_tag = shutdown_tag;
if (have_shutdown_tag) {
grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_SHUTDOWN);
if (server->lists[ALL_CALLS] == NULL) {
grpc_cq_end_server_shutdown(server->cq, shutdown_tag);
}
}
gpr_mu_unlock(&server->mu); gpr_mu_unlock(&server->mu);
for (i = 0; i < nchannels; i++) { for (i = 0; i < nchannels; i++) {
@ -583,6 +598,14 @@ void grpc_server_shutdown(grpc_server *server) {
} }
} }
void grpc_server_shutdown(grpc_server *server) {
shutdown_internal(server, 0, NULL);
}
void grpc_server_shutdown_and_notify(grpc_server *server, void *tag) {
shutdown_internal(server, 1, tag);
}
void grpc_server_destroy(grpc_server *server) { void grpc_server_destroy(grpc_server *server) {
channel_data *c; channel_data *c;
gpr_mu_lock(&server->mu); gpr_mu_lock(&server->mu);

@ -1503,8 +1503,9 @@ static int process_read(transport *t, gpr_slice slice) {
"Connect string mismatch: expected '%c' (%d) got '%c' (%d) " "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
"at byte %d", "at byte %d",
CLIENT_CONNECT_STRING[t->deframe_state], CLIENT_CONNECT_STRING[t->deframe_state],
(int)(gpr_uint8)CLIENT_CONNECT_STRING[t->deframe_state], *cur, (int)(gpr_uint8) CLIENT_CONNECT_STRING[t->deframe_state],
(int)*cur, t->deframe_state); *cur, (int)*cur, t->deframe_state);
drop_connection(t);
return 0; return 0;
} }
++cur; ++cur;
@ -1738,8 +1739,8 @@ static void add_to_pollset(grpc_transport *gt, grpc_pollset *pollset) {
static const grpc_transport_vtable vtable = { static const grpc_transport_vtable vtable = {
sizeof(stream), init_stream, send_batch, set_allow_window_updates, sizeof(stream), init_stream, send_batch, set_allow_window_updates,
add_to_pollset, destroy_stream, abort_stream, goaway, close_transport, add_to_pollset, destroy_stream, abort_stream, goaway,
send_ping, destroy_transport}; close_transport, send_ping, destroy_transport};
void grpc_create_chttp2_transport(grpc_transport_setup_callback setup, void grpc_create_chttp2_transport(grpc_transport_setup_callback setup,
void *arg, void *arg,

@ -230,9 +230,10 @@ static void tsi_fake_frame_destruct(tsi_fake_frame* frame) {
/* --- tsi_frame_protector methods implementation. ---*/ /* --- tsi_frame_protector methods implementation. ---*/
static tsi_result fake_protector_protect( static tsi_result fake_protector_protect(tsi_frame_protector* self,
tsi_frame_protector* self, const unsigned char* unprotected_bytes, const unsigned char* unprotected_bytes,
size_t* unprotected_bytes_size, unsigned char* protected_output_frames, size_t* unprotected_bytes_size,
unsigned char* protected_output_frames,
size_t* protected_output_frames_size) { size_t* protected_output_frames_size) {
tsi_result result = TSI_OK; tsi_result result = TSI_OK;
tsi_fake_frame_protector* impl = (tsi_fake_frame_protector*)self; tsi_fake_frame_protector* impl = (tsi_fake_frame_protector*)self;
@ -480,8 +481,10 @@ static void fake_handshaker_destroy(tsi_handshaker* self) {
static const tsi_handshaker_vtable handshaker_vtable = { static const tsi_handshaker_vtable handshaker_vtable = {
fake_handshaker_get_bytes_to_send_to_peer, fake_handshaker_get_bytes_to_send_to_peer,
fake_handshaker_process_bytes_from_peer, fake_handshaker_get_result, fake_handshaker_process_bytes_from_peer,
fake_handshaker_extract_peer, fake_handshaker_create_frame_protector, fake_handshaker_get_result,
fake_handshaker_extract_peer,
fake_handshaker_create_frame_protector,
fake_handshaker_destroy, fake_handshaker_destroy,
}; };

@ -573,9 +573,10 @@ static tsi_result build_alpn_protocol_name_list(
/* --- tsi_frame_protector methods implementation. ---*/ /* --- tsi_frame_protector methods implementation. ---*/
static tsi_result ssl_protector_protect( static tsi_result ssl_protector_protect(tsi_frame_protector* self,
tsi_frame_protector* self, const unsigned char* unprotected_bytes, const unsigned char* unprotected_bytes,
size_t* unprotected_bytes_size, unsigned char* protected_output_frames, size_t* unprotected_bytes_size,
unsigned char* protected_output_frames,
size_t* protected_output_frames_size) { size_t* protected_output_frames_size) {
tsi_ssl_frame_protector* impl = (tsi_ssl_frame_protector*)self; tsi_ssl_frame_protector* impl = (tsi_ssl_frame_protector*)self;
int read_from_ssl; int read_from_ssl;
@ -707,8 +708,9 @@ static const tsi_frame_protector_vtable frame_protector_vtable = {
/* --- tsi_handshaker methods implementation. ---*/ /* --- tsi_handshaker methods implementation. ---*/
static tsi_result ssl_handshaker_get_bytes_to_send_to_peer( static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker* self,
tsi_handshaker* self, unsigned char* bytes, size_t* bytes_size) { unsigned char* bytes,
size_t* bytes_size) {
tsi_ssl_handshaker* impl = (tsi_ssl_handshaker*)self; tsi_ssl_handshaker* impl = (tsi_ssl_handshaker*)self;
int bytes_read_from_ssl = 0; int bytes_read_from_ssl = 0;
if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 || if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 ||
@ -871,8 +873,10 @@ static void ssl_handshaker_destroy(tsi_handshaker* self) {
static const tsi_handshaker_vtable handshaker_vtable = { static const tsi_handshaker_vtable handshaker_vtable = {
ssl_handshaker_get_bytes_to_send_to_peer, ssl_handshaker_get_bytes_to_send_to_peer,
ssl_handshaker_process_bytes_from_peer, ssl_handshaker_get_result, ssl_handshaker_process_bytes_from_peer,
ssl_handshaker_extract_peer, ssl_handshaker_create_frame_protector, ssl_handshaker_get_result,
ssl_handshaker_extract_peer,
ssl_handshaker_create_frame_protector,
ssl_handshaker_destroy, ssl_handshaker_destroy,
}; };
@ -1157,8 +1161,7 @@ tsi_result tsi_create_ssl_client_handshaker_factory(
tsi_result tsi_create_ssl_server_handshaker_factory( tsi_result tsi_create_ssl_server_handshaker_factory(
const unsigned char** pem_private_keys, const unsigned char** pem_private_keys,
const size_t* pem_private_keys_sizes, const size_t* pem_private_keys_sizes, const unsigned char** pem_cert_chains,
const unsigned char** pem_cert_chains,
const size_t* pem_cert_chains_sizes, size_t key_cert_pair_count, const size_t* pem_cert_chains_sizes, size_t key_cert_pair_count,
const unsigned char* pem_client_root_certs, const unsigned char* pem_client_root_certs,
size_t pem_client_root_certs_size, const char* cipher_list, size_t pem_client_root_certs_size, const char* cipher_list,

@ -132,8 +132,7 @@ tsi_result tsi_create_ssl_client_handshaker_factory(
where a parameter is invalid. */ where a parameter is invalid. */
tsi_result tsi_create_ssl_server_handshaker_factory( tsi_result tsi_create_ssl_server_handshaker_factory(
const unsigned char** pem_private_keys, const unsigned char** pem_private_keys,
const size_t* pem_private_keys_sizes, const size_t* pem_private_keys_sizes, const unsigned char** pem_cert_chains,
const unsigned char** pem_cert_chains,
const size_t* pem_cert_chains_sizes, size_t key_cert_pair_count, const size_t* pem_cert_chains_sizes, size_t key_cert_pair_count,
const unsigned char* pem_client_root_certs, const unsigned char* pem_client_root_certs,
size_t pem_client_root_certs_size, const char* cipher_suites, size_t pem_client_root_certs_size, const char* cipher_suites,

@ -65,8 +65,8 @@ CompletionQueue::CompletionType CompletionQueue::Next(void** tag) {
case GRPC_READ: case GRPC_READ:
*tag = ev->tag; *tag = ev->tag;
if (ev->data.read) { if (ev->data.read) {
success = success = static_cast<AsyncServerContext *>(ev->tag)
static_cast<AsyncServerContext*>(ev->tag)->ParseRead(ev->data.read); ->ParseRead(ev->data.read);
return_type = success ? SERVER_READ_OK : SERVER_READ_ERROR; return_type = success ? SERVER_READ_OK : SERVER_READ_ERROR;
} else { } else {
return_type = SERVER_READ_ERROR; return_type = SERVER_READ_ERROR;

@ -77,7 +77,9 @@ class StreamContext final : public StreamContextInterface {
void *write_tag() { return reinterpret_cast<char *>(this) + 2; } void *write_tag() { return reinterpret_cast<char *>(this) + 2; }
void *halfclose_tag() { return reinterpret_cast<char *>(this) + 3; } void *halfclose_tag() { return reinterpret_cast<char *>(this) + 3; }
void *invoke_tag() { return reinterpret_cast<char *>(this) + 4; } void *invoke_tag() { return reinterpret_cast<char *>(this) + 4; }
void* client_metadata_read_tag() { return reinterpret_cast<char*>(this) + 5; } void *client_metadata_read_tag() {
return reinterpret_cast<char *>(this) + 5;
}
grpc_call *call() { return call_; } grpc_call *call() { return call_; }
grpc_completion_queue *cq() { return cq_; } grpc_completion_queue *cq() { return cq_; }

@ -16,3 +16,6 @@ install-sh
libtool libtool
missing missing
mkinstalldirs mkinstalldirs
ext/grpc/ltmain.sh

@ -1,5 +1,17 @@
#!/bin/sh
# Loads the local shared library, and runs all of the test cases in tests/ # Loads the local shared library, and runs all of the test cases in tests/
# against it # against it
set -e
cd $(dirname $0) cd $(dirname $0)
php -d extension_dir=../ext/grpc/modules/ -d extension=grpc.so \ default_extension_dir=`php -i | grep extension_dir | sed 's/.*=> //g'`
/usr/local/bin/phpunit -v --debug --strict ../tests/unit_tests
# sym-link in system supplied extensions
for f in $default_extension_dir/*.so
do
ln -s $f ../ext/grpc/modules/$(basename $f) &> /dev/null || true
done
php \
-d extension_dir=../ext/grpc/modules/ \
-d extension=grpc.so \
`which phpunit` -v --debug --strict ../tests/unit_tests

@ -425,14 +425,13 @@ static zend_function_entry call_methods[] = {
PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ME(Call, server_accept, NULL, ZEND_ACC_PUBLIC) PHP_ME(Call, server_accept, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Call, server_end_initial_metadata, NULL, ZEND_ACC_PUBLIC) PHP_ME(Call, server_end_initial_metadata, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Call, add_metadata, NULL, ZEND_ACC_PUBLIC) PHP_ME( PHP_ME(Call, add_metadata, NULL, ZEND_ACC_PUBLIC)
Call, cancel, NULL, ZEND_ACC_PUBLIC) PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Call, start_invoke, NULL, ZEND_ACC_PUBLIC) PHP_ME( PHP_ME(Call, start_invoke, NULL, ZEND_ACC_PUBLIC)
Call, start_read, NULL, ZEND_ACC_PUBLIC) PHP_ME(Call, start_read, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Call, start_write, NULL, ZEND_ACC_PUBLIC) PHP_ME( PHP_ME(Call, start_write, NULL, ZEND_ACC_PUBLIC)
Call, start_write_status, NULL, ZEND_ACC_PUBLIC) PHP_ME(Call, start_write_status, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Call, writes_done, NULL, ZEND_ACC_PUBLIC) PHP_ME(Call, writes_done, NULL, ZEND_ACC_PUBLIC) PHP_FE_END};
PHP_FE_END};
void grpc_init_call(TSRMLS_D) { void grpc_init_call(TSRMLS_D) {
zend_class_entry ce; zend_class_entry ce;

@ -63,8 +63,8 @@ zend_object_value create_wrapped_grpc_completion_queue(
*/ */
PHP_METHOD(CompletionQueue, __construct) { PHP_METHOD(CompletionQueue, __construct) {
wrapped_grpc_completion_queue *queue = wrapped_grpc_completion_queue *queue =
(wrapped_grpc_completion_queue *)zend_object_store_get_object( (wrapped_grpc_completion_queue *)zend_object_store_get_object(getThis()
getThis() TSRMLS_CC); TSRMLS_CC);
queue->wrapped = grpc_completion_queue_create(); queue->wrapped = grpc_completion_queue_create();
} }
@ -86,8 +86,8 @@ PHP_METHOD(CompletionQueue, next) {
return; return;
} }
wrapped_grpc_completion_queue *completion_queue = wrapped_grpc_completion_queue *completion_queue =
(wrapped_grpc_completion_queue *)zend_object_store_get_object( (wrapped_grpc_completion_queue *)zend_object_store_get_object(getThis()
getThis() TSRMLS_CC); TSRMLS_CC);
wrapped_grpc_timeval *wrapped_timeout = wrapped_grpc_timeval *wrapped_timeout =
(wrapped_grpc_timeval *)zend_object_store_get_object(timeout TSRMLS_CC); (wrapped_grpc_timeval *)zend_object_store_get_object(timeout TSRMLS_CC);
grpc_event *event = grpc_completion_queue_next(completion_queue->wrapped, grpc_event *event = grpc_completion_queue_next(completion_queue->wrapped,
@ -109,8 +109,8 @@ PHP_METHOD(CompletionQueue, pluck) {
"pluck needs a long and a Timeval", 1 TSRMLS_CC); "pluck needs a long and a Timeval", 1 TSRMLS_CC);
} }
wrapped_grpc_completion_queue *completion_queue = wrapped_grpc_completion_queue *completion_queue =
(wrapped_grpc_completion_queue *)zend_object_store_get_object( (wrapped_grpc_completion_queue *)zend_object_store_get_object(getThis()
getThis() TSRMLS_CC); TSRMLS_CC);
wrapped_grpc_timeval *wrapped_timeout = wrapped_grpc_timeval *wrapped_timeout =
(wrapped_grpc_timeval *)zend_object_store_get_object(timeout TSRMLS_CC); (wrapped_grpc_timeval *)zend_object_store_get_object(timeout TSRMLS_CC);
grpc_event *event = grpc_completion_queue_pluck( grpc_event *event = grpc_completion_queue_pluck(

@ -38,7 +38,9 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD) PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(rt) PHP_ADD_LIBRARY(rt)
PHP_ADD_LIBPATH($GRPC_DIR/lib) GRPC_LIBDIR=$GRPC_DIR/${GRPC_LIB_SUBDIR-lib}
PHP_ADD_LIBPATH($GRPC_LIBDIR)
PHP_CHECK_LIBRARY(gpr,gpr_now, PHP_CHECK_LIBRARY(gpr,gpr_now,
[ [
@ -48,18 +50,9 @@ if test "$PHP_GRPC" != "no"; then
],[ ],[
AC_MSG_ERROR([wrong gpr lib version or lib not found]) AC_MSG_ERROR([wrong gpr lib version or lib not found])
],[ ],[
-L$GRPC_DIR/lib -L$GRPC_LIBDIR
]) ])
PHP_ADD_LIBRARY(event,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(event)
PHP_ADD_LIBRARY(event_pthreads,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(event_pthreads)
PHP_ADD_LIBRARY(event_core,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(event_core)
PHP_CHECK_LIBRARY(grpc,grpc_channel_destroy, PHP_CHECK_LIBRARY(grpc,grpc_channel_destroy,
[ [
PHP_ADD_LIBRARY(grpc,,GRPC_SHARED_LIBADD) PHP_ADD_LIBRARY(grpc,,GRPC_SHARED_LIBADD)
@ -68,7 +61,7 @@ if test "$PHP_GRPC" != "no"; then
],[ ],[
AC_MSG_ERROR([wrong grpc lib version or lib not found]) AC_MSG_ERROR([wrong grpc lib version or lib not found])
],[ ],[
-L$GRPC_DIR/lib -L$GRPC_LIBDIR
]) ])
PHP_SUBST(GRPC_SHARED_LIBADD) PHP_SUBST(GRPC_SHARED_LIBADD)

@ -154,10 +154,9 @@ static zend_function_entry credentials_methods[] = {
PHP_ME(Credentials, createSsl, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Credentials, createSsl, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(Credentials, createComposite, NULL, PHP_ME(Credentials, createComposite, NULL,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(Credentials, createGce, NULL, PHP_ME(Credentials, createGce, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Credentials, createFake, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(Credentials, createFake, NULL, PHP_FE_END};
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END};
void grpc_init_credentials(TSRMLS_D) { void grpc_init_credentials(TSRMLS_D) {
zend_class_entry ce; zend_class_entry ce;

@ -33,7 +33,8 @@ zend_module_entry grpc_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901 #if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER, STANDARD_MODULE_HEADER,
#endif #endif
"grpc", grpc_functions, PHP_MINIT(grpc), PHP_MSHUTDOWN(grpc), NULL, NULL, "grpc", grpc_functions, PHP_MINIT(grpc),
PHP_MSHUTDOWN(grpc), NULL, NULL,
PHP_MINFO(grpc), PHP_MINFO(grpc),
#if ZEND_MODULE_API_NO >= 20010901 #if ZEND_MODULE_API_NO >= 20010901
PHP_GRPC_VERSION, PHP_GRPC_VERSION,

@ -217,20 +217,16 @@ PHP_METHOD(Timeval, sleep_until) {
} }
static zend_function_entry timeval_methods[] = { static zend_function_entry timeval_methods[] = {
PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME( PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
Timeval, add, NULL, PHP_ME(Timeval, add, NULL, ZEND_ACC_PUBLIC)
ZEND_ACC_PUBLIC) PHP_ME(Timeval, compare, NULL, PHP_ME(Timeval, compare, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(Timeval, inf_future, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Timeval, inf_future, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(Timeval, inf_past, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Timeval, inf_past, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(Timeval, similar, NULL, PHP_ME(Timeval, similar, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(Timeval, sleep_until, NULL, ZEND_ACC_PUBLIC) PHP_ME(Timeval, sleep_until, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC) PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Timeval, zero, NULL, PHP_ME(Timeval, zero, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END};
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_FE_END};
void grpc_init_timeval(TSRMLS_D) { void grpc_init_timeval(TSRMLS_D) {
zend_class_entry ce; zend_class_entry ce;

@ -0,0 +1,10 @@
# This is the configuration used to check the rubocop source code.
inherit_from: .rubocop_todo.yml
AllCops:
Exclude:
- 'bin/apis/**/*'
- 'bin/interop/test/**/*'
- 'bin/math.rb'
- 'bin/math_services.rb'

@ -0,0 +1,52 @@
# This configuration was generated by `rubocop --auto-gen-config`
# on 2015-01-16 02:30:04 -0800 using RuboCop version 0.28.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 3
# Lint/UselessAssignment:
# Enabled: false
# Offense count: 33
Metrics/AbcSize:
Max: 39
# Offense count: 3
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 231
# Offense count: 2
Metrics/CyclomaticComplexity:
Max: 8
# Offense count: 36
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 37
# Offense count: 8
# Configuration parameters: CountKeywordArgs.
Metrics/ParameterLists:
Max: 8
# Offense count: 2
Metrics/PerceivedComplexity:
Max: 10
# Offense count: 7
# Configuration parameters: AllowedVariables.
Style/GlobalVars:
Enabled: false
# Offense count: 1
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
Style/Next:
Enabled: false
# Offense count: 2
# Configuration parameters: Methods.
Style/SingleLineBlockParams:
Enabled: false

@ -1,46 +1,44 @@
# -*- ruby -*- # -*- ruby -*-
require 'rake/extensiontask' require 'rake/extensiontask'
require 'rspec/core/rake_task' require 'rspec/core/rake_task'
require 'rubocop/rake_task'
desc 'Run Rubocop to check for style violations'
RuboCop::RakeTask.new
Rake::ExtensionTask.new 'grpc' do |ext| Rake::ExtensionTask.new 'grpc' do |ext|
ext.lib_dir = File.join('lib', 'grpc') ext.lib_dir = File.join('lib', 'grpc')
end end
SPEC_SUITES = [ SPEC_SUITES = [
{ :id => :wrapper, :title => 'wrapper layer', :files => %w(spec/*.rb) }, { id: :wrapper, title: 'wrapper layer', files: %w(spec/*.rb) },
{ :id => :idiomatic, :title => 'idiomatic layer', :dir => %w(spec/generic), { id: :idiomatic, title: 'idiomatic layer', dir: %w(spec/generic),
:tag => '~bidi' }, tag: '~bidi' },
{ :id => :bidi, :title => 'bidi tests', :dir => %w(spec/generic), { id: :bidi, title: 'bidi tests', dir: %w(spec/generic),
:tag => 'bidi' } tag: 'bidi' }
] ]
desc "Run all RSpec tests" desc 'Run all RSpec tests'
namespace :spec do namespace :spec do
namespace :suite do namespace :suite do
SPEC_SUITES.each do |suite| SPEC_SUITES.each do |suite|
desc "Run all specs in #{suite[:title]} spec suite" desc "Run all specs in #{suite[:title]} spec suite"
RSpec::Core::RakeTask.new(suite[:id]) do |t| RSpec::Core::RakeTask.new(suite[:id]) do |t|
spec_files = [] spec_files = []
if suite[:files] suite[:files].each { |f| spec_files += Dir[f] } if suite[:files]
suite[:files].each { |f| spec_files += Dir[f] }
end
if suite[:dirs] if suite[:dirs]
suite[:dirs].each { |f| spec_files += Dir["#{f}/**/*_spec.rb"] } suite[:dirs].each { |f| spec_files += Dir["#{f}/**/*_spec.rb"] }
end end
t.pattern = spec_files t.pattern = spec_files
t.rspec_opts = "--tag #{suite[:tag]}" if suite[:tag]
if suite[:tag]
t.rspec_opts = "--tag #{suite[:tag]}"
end
end end
end end
end end
end end
task :default => "spec:suite:idiomatic" # this should be spec:suite:bidi task default: 'spec:suite:idiomatic' # this should be spec:suite:bidi
task "spec:suite:wrapper" => :compile task 'spec:suite:wrapper' => :compile
task "spec:suite:idiomatic" => "spec:suite:wrapper" task 'spec:suite:idiomatic' => 'spec:suite:wrapper'
task "spec:suite:bidi" => "spec:suite:idiomatic" task 'spec:suite:bidi' => 'spec:suite:idiomatic'

@ -65,7 +65,7 @@ end
# creates a Credentials from the test certificates. # creates a Credentials from the test certificates.
def test_creds def test_creds
certs = load_test_certs certs = load_test_certs
creds = GRPC::Core::Credentials.new(certs[0]) GRPC::Core::Credentials.new(certs[0])
end end
# creates a test stub that accesses host:port securely. # creates a test stub that accesses host:port securely.
@ -73,15 +73,15 @@ def create_stub(host, port)
address = "#{host}:#{port}" address = "#{host}:#{port}"
stub_opts = { stub_opts = {
:creds => test_creds, :creds => test_creds,
GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com', GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com'
} }
logger.info("... connecting securely to #{address}") logger.info("... connecting securely to #{address}")
stub = Grpc::Testing::TestService::Stub.new(address, **stub_opts) Grpc::Testing::TestService::Stub.new(address, **stub_opts)
end end
# produces a string of null chars (\0) of length l. # produces a string of null chars (\0) of length l.
def nulls(l) def nulls(l)
raise 'requires #{l} to be +ve' if l < 0 fail 'requires #{l} to be +ve' if l < 0
[].pack('x' * l).force_encoding('utf-8') [].pack('x' * l).force_encoding('utf-8')
end end
@ -106,9 +106,9 @@ class PingPongPlayer
count = 0 count = 0
@msg_sizes.each do |m| @msg_sizes.each do |m|
req_size, resp_size = m req_size, resp_size = m
req = req_cls.new(:payload => Payload.new(:body => nulls(req_size)), req = req_cls.new(payload: Payload.new(body: nulls(req_size)),
:response_type => COMPRESSABLE, response_type: COMPRESSABLE,
:response_parameters => [p_cls.new(:size => resp_size)]) response_parameters: [p_cls.new(size: resp_size)])
yield req yield req
resp = @queue.pop resp = @queue.pop
assert_equal(PayloadType.lookup(COMPRESSABLE), resp.payload.type, assert_equal(PayloadType.lookup(COMPRESSABLE), resp.payload.type,
@ -148,11 +148,11 @@ class NamedTests
# ruby server # ruby server
# FAILED # FAILED
def large_unary def large_unary
req_size, wanted_response_size = 271828, 314159 req_size, wanted_response_size = 271_828, 314_159
payload = Payload.new(:type => COMPRESSABLE, :body => nulls(req_size)) payload = Payload.new(type: COMPRESSABLE, body: nulls(req_size))
req = SimpleRequest.new(:response_type => COMPRESSABLE, req = SimpleRequest.new(response_type: COMPRESSABLE,
:response_size => wanted_response_size, response_size: wanted_response_size,
:payload => payload) payload: payload)
resp = @stub.unary_call(req) resp = @stub.unary_call(req)
assert_equal(wanted_response_size, resp.payload.body.length, assert_equal(wanted_response_size, resp.payload.body.length,
'large_unary: payload had the wrong length') 'large_unary: payload had the wrong length')
@ -166,11 +166,11 @@ class NamedTests
# ruby server # ruby server
# FAILED # FAILED
def client_streaming def client_streaming
msg_sizes = [27182, 8, 1828, 45904] msg_sizes = [27_182, 8, 1828, 45_904]
wanted_aggregate_size = 74922 wanted_aggregate_size = 74_922
reqs = msg_sizes.map do |x| reqs = msg_sizes.map do |x|
req = Payload.new(:body => nulls(x)) req = Payload.new(body: nulls(x))
StreamingInputCallRequest.new(:payload => req) StreamingInputCallRequest.new(payload: req)
end end
resp = @stub.streaming_input_call(reqs) resp = @stub.streaming_input_call(reqs)
assert_equal(wanted_aggregate_size, resp.aggregated_payload_size, assert_equal(wanted_aggregate_size, resp.aggregated_payload_size,
@ -183,10 +183,10 @@ class NamedTests
# ruby server # ruby server
# FAILED # FAILED
def server_streaming def server_streaming
msg_sizes = [31415, 9, 2653, 58979] msg_sizes = [31_415, 9, 2653, 58_979]
response_spec = msg_sizes.map { |s| ResponseParameters.new(:size => s) } response_spec = msg_sizes.map { |s| ResponseParameters.new(size: s) }
req = StreamingOutputCallRequest.new(:response_type => COMPRESSABLE, req = StreamingOutputCallRequest.new(response_type: COMPRESSABLE,
:response_parameters => response_spec) response_parameters: response_spec)
resps = @stub.streaming_output_call(req) resps = @stub.streaming_output_call(req)
resps.each_with_index do |r, i| resps.each_with_index do |r, i|
assert i < msg_sizes.length, 'too many responses' assert i < msg_sizes.length, 'too many responses'
@ -203,13 +203,12 @@ class NamedTests
# ruby server # ruby server
# FAILED # FAILED
def ping_pong def ping_pong
msg_sizes = [[27182, 31415], [8, 9], [1828, 2653], [45904, 58979]] msg_sizes = [[27_182, 31_415], [8, 9], [1828, 2653], [45_904, 58_979]]
ppp = PingPongPlayer.new(msg_sizes) ppp = PingPongPlayer.new(msg_sizes)
resps = @stub.full_duplex_call(ppp.each_item) resps = @stub.full_duplex_call(ppp.each_item)
resps.each { |r| ppp.queue.push(r) } resps.each { |r| ppp.queue.push(r) }
p 'OK: ping_pong' p 'OK: ping_pong'
end end
end end
# validates the the command line options, returning them as a Hash. # validates the the command line options, returning them as a Hash.
@ -217,7 +216,7 @@ def parse_options
options = { options = {
'server_host' => nil, 'server_host' => nil,
'server_port' => nil, 'server_port' => nil,
'test_case' => nil, 'test_case' => nil
} }
OptionParser.new do |opts| OptionParser.new do |opts|
opts.banner = 'Usage: --server_host <server_host> --server_port server_port' opts.banner = 'Usage: --server_host <server_host> --server_port server_port'
@ -228,17 +227,17 @@ def parse_options
options['server_port'] = v options['server_port'] = v
end end
# instance_methods(false) gives only the methods defined in that class # instance_methods(false) gives only the methods defined in that class
test_cases = NamedTests.instance_methods(false).map { |t| t.to_s } test_cases = NamedTests.instance_methods(false).map(&:to_s)
test_case_list = test_cases.join(',') test_case_list = test_cases.join(',')
opts.on("--test_case CODE", test_cases, {}, "select a test_case", opts.on('--test_case CODE', test_cases, {}, 'select a test_case',
" (#{test_case_list})") do |v| " (#{test_case_list})") do |v|
options['test_case'] = v options['test_case'] = v
end end
end.parse! end.parse!
['server_host', 'server_port', 'test_case'].each do |arg| %w(server_host, server_port, test_case).each do |arg|
if options[arg].nil? if options[arg].nil?
raise OptionParser::MissingArgument.new("please specify --#{arg}") fail(OptionParser::MissingArgument, "please specify --#{arg}")
end end
end end
options options

@ -62,12 +62,12 @@ end
# creates a ServerCredentials from the test certificates. # creates a ServerCredentials from the test certificates.
def test_server_creds def test_server_creds
certs = load_test_certs certs = load_test_certs
server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
end end
# produces a string of null chars (\0) of length l. # produces a string of null chars (\0) of length l.
def nulls(l) def nulls(l)
raise 'requires #{l} to be +ve' if l < 0 fail 'requires #{l} to be +ve' if l < 0
[].pack('x' * l).force_encoding('utf-8') [].pack('x' * l).force_encoding('utf-8')
end end
@ -86,7 +86,7 @@ class EnumeratorQueue
loop do loop do
r = @q.pop r = @q.pop
break if r.equal?(@sentinel) break if r.equal?(@sentinel)
raise r if r.is_a?Exception fail r if r.is_a? Exception
yield r yield r
end end
end end
@ -98,27 +98,27 @@ class TestTarget < Grpc::Testing::TestService::Service
include Grpc::Testing include Grpc::Testing
include Grpc::Testing::PayloadType include Grpc::Testing::PayloadType
def empty_call(empty, call) def empty_call(_empty, _call)
Empty.new Empty.new
end end
def unary_call(simple_req, call) def unary_call(simple_req, _call)
req_size = simple_req.response_size req_size = simple_req.response_size
SimpleResponse.new(:payload => Payload.new(:type => COMPRESSABLE, SimpleResponse.new(payload: Payload.new(type: COMPRESSABLE,
:body => nulls(req_size))) body: nulls(req_size)))
end end
def streaming_input_call(call) def streaming_input_call(call)
sizes = call.each_remote_read.map { |x| x.payload.body.length } sizes = call.each_remote_read.map { |x| x.payload.body.length }
sum = sizes.inject { |sum,x| sum + x } sum = sizes.inject { |s, x| s + x }
StreamingInputCallResponse.new(:aggregated_payload_size => sum) StreamingInputCallResponse.new(aggregated_payload_size: sum)
end end
def streaming_output_call(req, call) def streaming_output_call(req, _call)
cls = StreamingOutputCallResponse cls = StreamingOutputCallResponse
req.response_parameters.map do |p| req.response_parameters.map do |p|
cls.new(:payload => Payload.new(:type => req.response_type, cls.new(payload: Payload.new(type: req.response_type,
:body => nulls(p.size))) body: nulls(p.size)))
end end
end end
@ -126,13 +126,13 @@ class TestTarget < Grpc::Testing::TestService::Service
# reqs is a lazy Enumerator of the requests sent by the client. # reqs is a lazy Enumerator of the requests sent by the client.
q = EnumeratorQueue.new(self) q = EnumeratorQueue.new(self)
cls = StreamingOutputCallResponse cls = StreamingOutputCallResponse
t = Thread.new do Thread.new do
begin begin
reqs.each do |req| reqs.each do |req|
logger.info("read #{req.inspect}") logger.info("read #{req.inspect}")
resp_size = req.response_parameters[0].size resp_size = req.response_parameters[0].size
resp = cls.new(:payload => Payload.new(:type => req.response_type, resp = cls.new(payload: Payload.new(type: req.response_type,
:body => nulls(resp_size))) body: nulls(resp_size)))
q.push(resp) q.push(resp)
end end
logger.info('finished reads') logger.info('finished reads')
@ -149,13 +149,12 @@ class TestTarget < Grpc::Testing::TestService::Service
# currently used in any tests # currently used in any tests
full_duplex_call(reqs) full_duplex_call(reqs)
end end
end end
# validates the the command line options, returning them as a Hash. # validates the the command line options, returning them as a Hash.
def parse_options def parse_options
options = { options = {
'port' => nil, 'port' => nil
} }
OptionParser.new do |opts| OptionParser.new do |opts|
opts.banner = 'Usage: --port port' opts.banner = 'Usage: --port port'
@ -165,7 +164,7 @@ def parse_options
end.parse! end.parse!
if options['port'].nil? if options['port'].nil?
raise OptionParser::MissingArgument.new("please specify --port") fail(OptionParser::MissingArgument, 'please specify --port')
end end
options options
end end

@ -29,7 +29,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Sample app that accesses a Calc service running on a Ruby gRPC server and # Sample app that accesses a Calc service running on a Ruby gRPC server and
# helps validate RpcServer as a gRPC server using proto2 serialization. # helps validate RpcServer as a gRPC server using proto2 serialization.
# #
@ -49,9 +48,9 @@ include GRPC::Core::TimeConsts
def do_div(stub) def do_div(stub)
logger.info('request_response') logger.info('request_response')
logger.info('----------------') logger.info('----------------')
req = Math::DivArgs.new(:dividend => 7, :divisor => 3) req = Math::DivArgs.new(dividend: 7, divisor: 3)
logger.info("div(7/3): req=#{req.inspect}") logger.info("div(7/3): req=#{req.inspect}")
resp = stub.div(req, deadline=INFINITE_FUTURE) resp = stub.div(req, INFINITE_FUTURE)
logger.info("Answer: #{resp.inspect}") logger.info("Answer: #{resp.inspect}")
logger.info('----------------') logger.info('----------------')
end end
@ -60,7 +59,7 @@ def do_sum(stub)
# to make client streaming requests, pass an enumerable of the inputs # to make client streaming requests, pass an enumerable of the inputs
logger.info('client_streamer') logger.info('client_streamer')
logger.info('---------------') logger.info('---------------')
reqs = [1, 2, 3, 4, 5].map { |x| Math::Num.new(:num => x) } reqs = [1, 2, 3, 4, 5].map { |x| Math::Num.new(num: x) }
logger.info("sum(1, 2, 3, 4, 5): reqs=#{reqs.inspect}") logger.info("sum(1, 2, 3, 4, 5): reqs=#{reqs.inspect}")
resp = stub.sum(reqs) # reqs.is_a?(Enumerable) resp = stub.sum(reqs) # reqs.is_a?(Enumerable)
logger.info("Answer: #{resp.inspect}") logger.info("Answer: #{resp.inspect}")
@ -70,9 +69,9 @@ end
def do_fib(stub) def do_fib(stub)
logger.info('server_streamer') logger.info('server_streamer')
logger.info('----------------') logger.info('----------------')
req = Math::FibArgs.new(:limit => 11) req = Math::FibArgs.new(limit: 11)
logger.info("fib(11): req=#{req.inspect}") logger.info("fib(11): req=#{req.inspect}")
resp = stub.fib(req, deadline=INFINITE_FUTURE) resp = stub.fib(req, INFINITE_FUTURE)
resp.each do |r| resp.each do |r|
logger.info("Answer: #{r.inspect}") logger.info("Answer: #{r.inspect}")
end end
@ -83,11 +82,11 @@ def do_div_many(stub)
logger.info('bidi_streamer') logger.info('bidi_streamer')
logger.info('-------------') logger.info('-------------')
reqs = [] reqs = []
reqs << Math::DivArgs.new(:dividend => 7, :divisor => 3) reqs << Math::DivArgs.new(dividend: 7, divisor: 3)
reqs << Math::DivArgs.new(:dividend => 5, :divisor => 2) reqs << Math::Di5AvArgs.new(dividend: 5, divisor: 2)
reqs << Math::DivArgs.new(:dividend => 7, :divisor => 2) reqs << Math::DivArgs.new(dividend: 7, divisor: 2)
logger.info("div(7/3), div(5/2), div(7/2): reqs=#{reqs.inspect}") logger.info("div(7/3), div(5/2), div(7/2): reqs=#{reqs.inspect}")
resp = stub.div_many(reqs, deadline=10) resp = stub.div_many(reqs, 10)
resp.each do |r| resp.each do |r|
logger.info("Answer: #{r.inspect}") logger.info("Answer: #{r.inspect}")
end end
@ -103,7 +102,7 @@ end
def test_creds def test_creds
certs = load_test_certs certs = load_test_certs
creds = GRPC::Core::Credentials.new(certs[0]) GRPC::Core::Credentials.new(certs[0])
end end
def main def main
@ -117,7 +116,7 @@ def main
options['host'] = v options['host'] = v
end end
opts.on('-s', '--secure', 'access using test creds') do |v| opts.on('-s', '--secure', 'access using test creds') do |v|
options['secure'] = true options['secure'] = v
end end
end.parse! end.parse!
@ -128,7 +127,7 @@ def main
if options['secure'] if options['secure']
stub_opts = { stub_opts = {
:creds => test_creds, :creds => test_creds,
GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com', GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com'
} }
p stub_opts p stub_opts
p options['host'] p options['host']

@ -46,9 +46,8 @@ require 'optparse'
# Holds state for a fibonacci series # Holds state for a fibonacci series
class Fibber class Fibber
def initialize(limit) def initialize(limit)
raise "bad limit: got #{limit}, want limit > 0" if limit < 1 fail "bad limit: got #{limit}, want limit > 0" if limit < 1
@limit = limit @limit = limit
end end
@ -57,14 +56,14 @@ class Fibber
idx, current, previous = 0, 1, 1 idx, current, previous = 0, 1, 1
until idx == @limit until idx == @limit
if idx == 0 || idx == 1 if idx == 0 || idx == 1
yield Math::Num.new(:num => 1) yield Math::Num.new(num: 1)
idx += 1 idx += 1
next next
end end
tmp = current tmp = current
current = previous + current current = previous + current
previous = tmp previous = tmp
yield Math::Num.new(:num => current) yield Math::Num.new(num: current)
idx += 1 idx += 1
end end
end end
@ -85,43 +84,41 @@ class EnumeratorQueue
loop do loop do
r = @q.pop r = @q.pop
break if r.equal?(@sentinel) break if r.equal?(@sentinel)
raise r if r.is_a?Exception fail r if r.is_a? Exception
yield r yield r
end end
end end
end end
# The Math::Math:: module occurs because the service has the same name as its # The Math::Math:: module occurs because the service has the same name as its
# package. That practice should be avoided by defining real services. # package. That practice should be avoided by defining real services.
class Calculator < Math::Math::Service class Calculator < Math::Math::Service
def div(div_args, _call)
def div(div_args, call)
if div_args.divisor == 0 if div_args.divisor == 0
# To send non-OK status handlers raise a StatusError with the code and # To send non-OK status handlers raise a StatusError with the code and
# and detail they want sent as a Status. # and detail they want sent as a Status.
raise GRPC::StatusError.new(GRPC::Status::INVALID_ARGUMENT, fail GRPC::StatusError.new(GRPC::Status::INVALID_ARGUMENT,
'divisor cannot be 0') 'divisor cannot be 0')
end end
Math::DivReply.new(:quotient => div_args.dividend/div_args.divisor, Math::DivReply.new(quotient: div_args.dividend / div_args.divisor,
:remainder => div_args.dividend % div_args.divisor) remainder: div_args.dividend % div_args.divisor)
end end
def sum(call) def sum(call)
# the requests are accesible as the Enumerator call#each_request # the requests are accesible as the Enumerator call#each_request
nums = call.each_remote_read.collect { |x| x.num } nums = call.each_remote_read.collect(&:num)
sum = nums.inject { |sum,x| sum + x } sum = nums.inject { |s, x| s + x }
Math::Num.new(:num => sum) Math::Num.new(num: sum)
end end
def fib(fib_args, call) def fib(fib_args, _call)
if fib_args.limit < 1 if fib_args.limit < 1
raise StatusError.new(Status::INVALID_ARGUMENT, 'limit must be >= 0') fail StatusError.new(Status::INVALID_ARGUMENT, 'limit must be >= 0')
end end
# return an Enumerator of Nums # return an Enumerator of Nums
Fibber.new(fib_args.limit).generator() Fibber.new(fib_args.limit).generator
# just return the generator, GRPC::GenericServer sends each actual response # just return the generator, GRPC::GenericServer sends each actual response
end end
@ -132,10 +129,10 @@ class Calculator < Math::Math::Service
begin begin
requests.each do |req| requests.each do |req|
logger.info("read #{req.inspect}") logger.info("read #{req.inspect}")
resp = Math::DivReply.new(:quotient => req.dividend/req.divisor, resp = Math::DivReply.new(quotient: req.dividend / req.divisor,
:remainder => req.dividend % req.divisor) remainder: req.dividend % req.divisor)
q.push(resp) q.push(resp)
Thread::pass # let the internal Bidi threads run Thread.pass # let the internal Bidi threads run
end end
logger.info('finished reads') logger.info('finished reads')
q.push(self) q.push(self)
@ -147,7 +144,6 @@ class Calculator < Math::Math::Service
t.priority = -2 # hint that the div_many thread should not be favoured t.priority = -2 # hint that the div_many thread should not be favoured
q.each_item q.each_item
end end
end end
def load_test_certs def load_test_certs
@ -159,7 +155,7 @@ end
def test_server_creds def test_server_creds
certs = load_test_certs certs = load_test_certs
server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
end end
def main def main
@ -173,7 +169,7 @@ def main
options['host'] = v options['host'] = v
end end
opts.on('-s', '--secure', 'access using test creds') do |v| opts.on('-s', '--secure', 'access using test creds') do |v|
options['secure'] = true options['secure'] = v
end end
end.parse! end.parse!

@ -40,16 +40,18 @@ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc' require 'grpc'
require 'optparse' require 'optparse'
# a simple non-protobuf message class.
class NoProtoMsg class NoProtoMsg
def self.marshal(o) def self.marshal(_o)
'' ''
end end
def self.unmarshal(o) def self.unmarshal(_o)
NoProtoMsg.new NoProtoMsg.new
end end
end end
# service the uses the non-protobuf message class.
class NoProtoService class NoProtoService
include GRPC::GenericService include GRPC::GenericService
rpc :AnRPC, NoProtoMsg, NoProtoMsg rpc :AnRPC, NoProtoMsg, NoProtoMsg
@ -66,7 +68,7 @@ end
def test_creds def test_creds
certs = load_test_certs certs = load_test_certs
creds = GRPC::Core::Credentials.new(certs[0]) GRPC::Core::Credentials.new(certs[0])
end end
def main def main
@ -80,14 +82,14 @@ def main
options['host'] = v options['host'] = v
end end
opts.on('-s', '--secure', 'access using test creds') do |v| opts.on('-s', '--secure', 'access using test creds') do |v|
options['secure'] = true options['secure'] = v
end end
end.parse! end.parse!
if options['secure'] if options['secure']
stub_opts = { stub_opts = {
:creds => test_creds, :creds => test_creds,
GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com', GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com'
} }
p stub_opts p stub_opts
p options['host'] p options['host']

@ -40,26 +40,29 @@ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc' require 'grpc'
require 'optparse' require 'optparse'
# a simple non-protobuf message class.
class NoProtoMsg class NoProtoMsg
def self.marshal(o) def self.marshal(_o)
'' ''
end end
def self.unmarshal(o) def self.unmarshal(_o)
NoProtoMsg.new NoProtoMsg.new
end end
end end
# service the uses the non-protobuf message class.
class NoProtoService class NoProtoService
include GRPC::GenericService include GRPC::GenericService
rpc :AnRPC, NoProtoMsg, NoProtoMsg rpc :AnRPC, NoProtoMsg, NoProtoMsg
end end
# an implementation of the non-protobuf service.
class NoProto < NoProtoService class NoProto < NoProtoService
def initialize(default_var='ignored') def initialize(_default_var = 'ignored')
end end
def an_rpc(req, call) def an_rpc(req, _call)
logger.info('echo service received a request') logger.info('echo service received a request')
req req
end end
@ -74,7 +77,7 @@ end
def test_server_creds def test_server_creds
certs = load_test_certs certs = load_test_certs
server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
end end
def main def main
@ -88,7 +91,7 @@ def main
options['host'] = v options['host'] = v
end end
opts.on('-s', '--secure', 'access using test creds') do |v| opts.on('-s', '--secure', 'access using test creds') do |v|
options['secure'] = true options['secure'] = v
end end
end.parse! end.parse!
@ -106,5 +109,4 @@ def main
s.run s.run
end end
main main

@ -40,7 +40,7 @@ HEADER_DIRS = [
'/usr/local/include', '/usr/local/include',
# Check the ruby install locations # Check the ruby install locations
INCLUDEDIR, INCLUDEDIR
] ]
LIB_DIRS = [ LIB_DIRS = [
@ -51,11 +51,11 @@ LIB_DIRS = [
'/usr/local/lib', '/usr/local/lib',
# Check the ruby install locations # Check the ruby install locations
LIBDIR, LIBDIR
] ]
def crash(msg) def crash(msg)
print(" extconf failure: %s\n" % msg) print(" extconf failure: #{msg}\n")
exit 1 exit 1
end end

@ -1,31 +1,34 @@
# encoding: utf-8 # encoding: utf-8
$:.push File.expand_path("../lib", __FILE__) $LOAD_PATH.push File.expand_path('../lib', __FILE__)
require 'grpc/version' require 'grpc/version'
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = "grpc" s.name = 'grpc'
s.version = Google::RPC::VERSION s.version = Google::RPC::VERSION
s.authors = ["One Platform Team"] s.authors = ['One Platform Team']
s.email = "stubby-team@google.com" s.email = 'stubby-team@google.com'
s.homepage = "http://go/grpc" s.homepage = 'http://go/grpc'
s.summary = 'Google RPC system in Ruby' s.summary = 'Google RPC system in Ruby'
s.description = 'Send RPCs from Ruby' s.description = 'Send RPCs from Ruby'
s.files = `git ls-files`.split("\n") s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- spec/*`.split("\n") s.test_files = `git ls-files -- spec/*`.split("\n")
s.executables = `git ls-files -- examples/*.rb`.split("\n").map{ |f| File.basename(f) } s.executables = `git ls-files -- bin/*.rb`.split("\n").map do |f|
File.basename(f)
end
s.require_paths = ['lib'] s.require_paths = ['lib']
s.platform = Gem::Platform::RUBY s.platform = Gem::Platform::RUBY
s.add_dependency 'xray' s.add_dependency 'xray'
s.add_dependency 'logging', '~> 1.8' s.add_dependency 'logging', '~> 1.8'
s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1' s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1'
s.add_dependency 'minitest', '~> 5.4' # not a dev dependency, used by the interop tests s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests
s.add_development_dependency "bundler", "~> 1.7" s.add_development_dependency 'bundler', '~> 1.7'
s.add_development_dependency "rake", "~> 10.0" s.add_development_dependency 'rake', '~> 10.0'
s.add_development_dependency 'rake-compiler', '~> 0' s.add_development_dependency 'rake-compiler', '~> 0'
s.add_development_dependency 'rspec', "~> 3.0" s.add_development_dependency 'rubocop', '~> 0.28.0'
s.add_development_dependency 'rspec', '~> 3.0'
s.extensions = %w[ext/grpc/extconf.rb] s.extensions = %w(ext/grpc/extconf.rb)
end end

@ -29,25 +29,21 @@
require 'beefcake' require 'beefcake'
module Beefcake
# Re-open the beefcake message module to add a static encode # Re-open the beefcake message module to add a static encode
# #
# This is a temporary measure while beefcake is used as the default proto # This is a temporary measure while beefcake is used as the default proto
# library for developing grpc ruby. Once that changes to the official proto # library for developing grpc ruby. Once that changes to the official proto
# library this can be removed. It's necessary to allow the update the service # library this can be removed. It's necessary to allow the update the service
# module to assume a static encode method. # module to assume a static encode method.
# # TODO(temiola): remove this.
# TODO(temiola): remove me, once official code generation is available in protoc
module Beefcake
module Message module Message
# additional mixin module that adds static encode method when include # additional mixin module that adds static encode method when include
module StaticEncode module StaticEncode
# encodes o with its instance#encode method # encodes o with its instance#encode method
def encode(o) def encode(o)
o.encode o.encode
end end
end end
# extend self.included in Beefcake::Message to include StaticEncode # extend self.included in Beefcake::Message to include StaticEncode
@ -57,6 +53,5 @@ module Beefcake
o.extend Decode o.extend Decode
o.send(:include, Encode) o.send(:include, Encode)
end end
end end
end end

@ -30,9 +30,12 @@
module Google module Google
module RPC module RPC
module Core module Core
class Event # Add an inspect method to C-defined Event class. # Event is a class defined in the c extension
#
# Here, we add an inspect method.
class Event
def inspect def inspect
'<%s: type:%s, tag:%s result:%s>' % [self.class, type, tag, result] "<#{self.class}: type:#{type}, tag:#{tag} result:#{result}>"
end end
end end
end end

@ -32,9 +32,10 @@ require 'grpc'
module Google module Google
module RPC module RPC
module Core module Core
# TimeConsts is a module from the C extension.
module TimeConsts # re-opens a module in the C extension. #
# Here it's re-opened to add a utility func.
module TimeConsts
# Converts a time delta to an absolute deadline. # Converts a time delta to an absolute deadline.
# #
# Assumes timeish is a relative time, and converts its to an absolute, # Assumes timeish is a relative time, and converts its to an absolute,
@ -53,19 +54,18 @@ module Google
elsif timeish.nil? elsif timeish.nil?
TimeConsts::ZERO TimeConsts::ZERO
elsif !timeish.is_a? Numeric elsif !timeish.is_a? Numeric
raise TypeError('Cannot make an absolute deadline from %s', fail(TypeError,
timeish.inspect) "Cannot make an absolute deadline from #{timeish.inspect}")
elsif timeish < 0 elsif timeish < 0
TimeConsts::INFINITE_FUTURE TimeConsts::INFINITE_FUTURE
elsif timeish == 0 elsif timeish == 0
TimeConsts::ZERO TimeConsts::ZERO
else !timeish.nil? else
Time.now + timeish Time.now + timeish
end end
end end
module_function :from_relative_time module_function :from_relative_time
end end
end end
end end

@ -30,9 +30,8 @@
require 'grpc' require 'grpc'
module Google module Google
# Google::RPC contains the General RPC module.
module RPC module RPC
# OutOfTime is an exception class that indicates that an RPC exceeded its # OutOfTime is an exception class that indicates that an RPC exceeded its
# deadline. # deadline.
OutOfTime = Class.new(StandardError) OutOfTime = Class.new(StandardError)
@ -42,7 +41,6 @@ module Google
# error should be returned to the other end of a GRPC connection; when # error should be returned to the other end of a GRPC connection; when
# caught it means that this end received a status error. # caught it means that this end received a status error.
class BadStatus < StandardError class BadStatus < StandardError
attr_reader :code, :details attr_reader :code, :details
# @param code [Numeric] the status code # @param code [Numeric] the status code
@ -60,9 +58,6 @@ module Google
def to_status def to_status
Status.new(code, details) Status.new(code, details)
end end
end end
end end
end end

@ -31,13 +31,14 @@ require 'forwardable'
require 'grpc/generic/bidi_call' require 'grpc/generic/bidi_call'
def assert_event_type(ev, want) def assert_event_type(ev, want)
raise OutOfTime if ev.nil? fail OutOfTime if ev.nil?
got = ev.type got = ev.type
raise 'Unexpected rpc event: got %s, want %s' % [got, want] unless got == want fail "Unexpected rpc event: got #{got}, want #{want}" unless got == want
end end
module Google::RPC module Google
# Google::RPC contains the General RPC module.
module RPC
# The ActiveCall class provides simple methods for sending marshallable # The ActiveCall class provides simple methods for sending marshallable
# data to a call # data to a call
class ActiveCall class ActiveCall
@ -60,19 +61,20 @@ module Google::RPC
# @param call [Call] a call on which to start and invocation # @param call [Call] a call on which to start and invocation
# @param q [CompletionQueue] used to wait for INVOKE_ACCEPTED # @param q [CompletionQueue] used to wait for INVOKE_ACCEPTED
# @param deadline [Fixnum,TimeSpec] the deadline for INVOKE_ACCEPTED # @param deadline [Fixnum,TimeSpec] the deadline for INVOKE_ACCEPTED
def self.client_start_invoke(call, q, deadline, **kw) def self.client_start_invoke(call, q, _deadline, **kw)
raise ArgumentError.new('not a call') unless call.is_a?Core::Call fail(ArgumentError, 'not a call') unless call.is_a? Core::Call
if !q.is_a?Core::CompletionQueue unless q.is_a? Core::CompletionQueue
raise ArgumentError.new('not a CompletionQueue') fail(ArgumentError, 'not a CompletionQueue')
end end
call.add_metadata(kw) if kw.length > 0 call.add_metadata(kw) if kw.length > 0
invoke_accepted, client_metadata_read = Object.new, Object.new invoke_accepted, client_metadata_read = Object.new, Object.new
finished_tag = Object.new finished_tag = Object.new
call.start_invoke(q, invoke_accepted, client_metadata_read, finished_tag) call.start_invoke(q, invoke_accepted, client_metadata_read,
finished_tag)
# wait for the invocation to be accepted # wait for the invocation to be accepted
ev = q.pluck(invoke_accepted, INFINITE_FUTURE) ev = q.pluck(invoke_accepted, INFINITE_FUTURE)
raise OutOfTime if ev.nil? fail OutOfTime if ev.nil?
ev.close ev.close
[finished_tag, client_metadata_read] [finished_tag, client_metadata_read]
@ -102,12 +104,12 @@ module Google::RPC
# if the call has begun # if the call has begun
# @param read_metadata_tag [Object] the object used as the call's finish # @param read_metadata_tag [Object] the object used as the call's finish
# tag, if the call has begun # tag, if the call has begun
# @param started [true|false] (default true) indicates if the call has begun # @param started [true|false] indicates if the call has begun
def initialize(call, q, marshal, unmarshal, deadline, finished_tag: nil, def initialize(call, q, marshal, unmarshal, deadline, finished_tag: nil,
read_metadata_tag: nil, started: true) read_metadata_tag: nil, started: true)
raise ArgumentError.new('not a call') unless call.is_a?Core::Call fail(ArgumentError, 'not a call') unless call.is_a? Core::Call
if !q.is_a?Core::CompletionQueue unless q.is_a? Core::CompletionQueue
raise ArgumentError.new('not a CompletionQueue') fail(ArgumentError, 'not a CompletionQueue')
end end
@call = call @call = call
@cq = q @cq = q
@ -147,8 +149,8 @@ module Google::RPC
# #
# - the call may terminate with a BadStatus exception, with code=CANCELLED # - the call may terminate with a BadStatus exception, with code=CANCELLED
# - the call may terminate with OK Status, and return a response # - the call may terminate with OK Status, and return a response
# - the call may terminate with a different BadStatus exception if that was # - the call may terminate with a different BadStatus exception if that
# happening # was happening
def cancel def cancel
@call.cancel @call.cancel
end end
@ -199,12 +201,11 @@ module Google::RPC
ev.close ev.close
end end
if assert_finished return unless assert_finished
ev = @cq.pluck(@finished_tag, INFINITE_FUTURE) ev = @cq.pluck(@finished_tag, INFINITE_FUTURE)
raise "unexpected event: #{ev.inspect}" if ev.nil? fail 'unexpected nil event' if ev.nil?
ev.close ev.close
return @call.status @call.status
end
end end
# finished waits until the call is completed. # finished waits until the call is completed.
@ -214,7 +215,7 @@ module Google::RPC
def finished def finished
ev = @cq.pluck(@finished_tag, INFINITE_FUTURE) ev = @cq.pluck(@finished_tag, INFINITE_FUTURE)
begin begin
raise "unexpected event: #{ev.inspect}" unless ev.type == FINISHED fail "unexpected event: #{ev.inspect}" unless ev.type == FINISHED
if @call.metadata.nil? if @call.metadata.nil?
@call.metadata = ev.result.metadata @call.metadata = ev.result.metadata
else else
@ -222,7 +223,7 @@ module Google::RPC
end end
if ev.result.code != Core::StatusCodes::OK if ev.result.code != Core::StatusCodes::OK
raise BadStatus.new(ev.result.code, ev.result.details) fail BadStatus.new(ev.result.code, ev.result.details)
end end
res = ev.result res = ev.result
ensure ensure
@ -241,7 +242,7 @@ module Google::RPC
# marshalled. # marshalled.
def remote_send(req, marshalled = false) def remote_send(req, marshalled = false)
assert_queue_is_ready assert_queue_is_ready
logger.debug("sending payload #{req.inspect}, marshalled? #{marshalled}") logger.debug("sending #{req.inspect}, marshalled? #{marshalled}")
if marshalled if marshalled
payload = req payload = req
else else
@ -275,9 +276,7 @@ module Google::RPC
ev.close ev.close
end end
logger.debug("Status sent: #{code}:'#{details}'") logger.debug("Status sent: #{code}:'#{details}'")
if assert_finished return finished if assert_finished
return finished
end
nil nil
end end
@ -285,7 +284,8 @@ module Google::RPC
# #
# It blocks until the remote endpoint sends a READ or FINISHED event. On # It blocks until the remote endpoint sends a READ or FINISHED event. On
# a READ, it returns the response after unmarshalling it. On # a READ, it returns the response after unmarshalling it. On
# FINISHED, it returns nil if the status is OK, otherwise raising BadStatus # FINISHED, it returns nil if the status is OK, otherwise raising
# BadStatus
def remote_read def remote_read
if @call.metadata.nil? && !@read_metadata_tag.nil? if @call.metadata.nil? && !@read_metadata_tag.nil?
ev = @cq.pluck(@read_metadata_tag, INFINITE_FUTURE) ev = @cq.pluck(@read_metadata_tag, INFINITE_FUTURE)
@ -299,8 +299,8 @@ module Google::RPC
begin begin
assert_event_type(ev, READ) assert_event_type(ev, READ)
logger.debug("received req: #{ev.result.inspect}") logger.debug("received req: #{ev.result.inspect}")
if !ev.result.nil? unless ev.result.nil?
logger.debug("received req.to_s: #{ev.result.to_s}") logger.debug("received req.to_s: #{ev.result}")
res = @unmarshal.call(ev.result.to_s) res = @unmarshal.call(ev.result.to_s)
logger.debug("received_req (unmarshalled): #{res.inspect}") logger.debug("received_req (unmarshalled): #{res.inspect}")
return res return res
@ -330,10 +330,10 @@ module Google::RPC
# #
# @return [Enumerator] if no block was given # @return [Enumerator] if no block was given
def each_remote_read def each_remote_read
return enum_for(:each_remote_read) if !block_given? return enum_for(:each_remote_read) unless block_given?
loop do loop do
resp = remote_read() resp = remote_read
break if resp.is_a?Struct::Status # is an OK status, bad statii raise break if resp.is_a? Struct::Status # is an OK status
break if resp.nil? # the last response was received break if resp.nil? # the last response was received
yield resp yield resp
end end
@ -360,10 +360,10 @@ module Google::RPC
# #
# @return [Enumerator] if no block was given # @return [Enumerator] if no block was given
def each_remote_read_then_finish def each_remote_read_then_finish
return enum_for(:each_remote_read_then_finish) if !block_given? return enum_for(:each_remote_read_then_finish) unless block_given?
loop do loop do
resp = remote_read resp = remote_read
break if resp.is_a?Struct::Status # is an OK status, bad statii raise break if resp.is_a? Struct::Status # is an OK status
if resp.nil? # the last response was received, but not finished yet if resp.nil? # the last response was received, but not finished yet
finished finished
break break
@ -386,9 +386,7 @@ module Google::RPC
remote_send(req) remote_send(req)
writes_done(false) writes_done(false)
response = remote_read response = remote_read
if !response.is_a?(Struct::Status) # finish if status not yet received finished unless response.is_a? Struct::Status
finished
end
response response
end end
@ -411,9 +409,7 @@ module Google::RPC
requests.each { |r| remote_send(r) } requests.each { |r| remote_send(r) }
writes_done(false) writes_done(false)
response = remote_read response = remote_read
if !response.is_a?(Struct::Status) # finish if status not yet received finished unless response.is_a? Struct::Status
finished
end
response response
end end
@ -439,7 +435,7 @@ module Google::RPC
remote_send(req) remote_send(req)
writes_done(false) writes_done(false)
replies = enum_for(:each_remote_read_then_finish) replies = enum_for(:each_remote_read_then_finish)
return replies if !block_given? return replies unless block_given?
replies.each { |r| yield r } replies.each { |r| yield r }
end end
@ -451,10 +447,11 @@ module Google::RPC
# #
# == requests == # == requests ==
# #
# requests provides an 'iterable' of Requests. I.e. it follows Ruby's #each # requests provides an 'iterable' of Requests. I.e. it follows Ruby's
# enumeration protocol. In the simplest case, requests will be an array of # #each enumeration protocol. In the simplest case, requests will be an
# marshallable objects; in typical case it will be an Enumerable that # array of marshallable objects; in typical case it will be an
# allows dynamic construction of the marshallable objects. # Enumerable that allows dynamic construction of the marshallable
# objects.
# #
# == responses == # == responses ==
# #
@ -526,8 +523,8 @@ module Google::RPC
# Operation limits access to an ActiveCall's methods for use as # Operation limits access to an ActiveCall's methods for use as
# a Operation on the client. # a Operation on the client.
Operation = view_class(:cancel, :cancelled, :deadline, :execute, :metadata, Operation = view_class(:cancel, :cancelled, :deadline, :execute,
:status) :metadata, :status)
# confirms that no events are enqueued, and that the queue is not # confirms that no events are enqueued, and that the queue is not
# shutdown. # shutdown.
@ -535,15 +532,15 @@ module Google::RPC
ev = nil ev = nil
begin begin
ev = @cq.pluck(self, ZERO) ev = @cq.pluck(self, ZERO)
raise "unexpected event #{ev.inspect}" unless ev.nil? fail "unexpected event #{ev.inspect}" unless ev.nil?
rescue OutOfTime rescue OutOfTime
logging.debug('timed out waiting for next event')
# expected, nothing should be on the queue and the deadline was ZERO, # expected, nothing should be on the queue and the deadline was ZERO,
# except things using another tag # except things using another tag
ensure ensure
ev.close unless ev.nil? ev.close unless ev.nil?
end end
end end
end end
end
end end

@ -31,13 +31,14 @@ require 'forwardable'
require 'grpc/grpc' require 'grpc/grpc'
def assert_event_type(ev, want) def assert_event_type(ev, want)
raise OutOfTime if ev.nil? fail OutOfTime if ev.nil?
got = ev.type got = ev.type
raise 'Unexpected rpc event: got %s, want %s' % [got, want] unless got == want fail("Unexpected rpc event: got #{got}, want #{want}") unless got == want
end end
module Google::RPC module Google
# Google::RPC contains the General RPC module.
module RPC
# The BiDiCall class orchestrates exection of a BiDi stream on a client or # The BiDiCall class orchestrates exection of a BiDi stream on a client or
# server. # server.
class BidiCall class BidiCall
@ -49,8 +50,9 @@ module Google::RPC
# #
# BidiCall should only be created after a call is accepted. That means # BidiCall should only be created after a call is accepted. That means
# different things on a client and a server. On the client, the call is # different things on a client and a server. On the client, the call is
# accepted after call.start_invoke followed by receipt of the corresponding # accepted after call.start_invoke followed by receipt of the
# INVOKE_ACCEPTED. On the server, this is after call.accept. # corresponding INVOKE_ACCEPTED. On the server, this is after
# call.accept.
# #
# #initialize cannot determine if the call is accepted or not; so if a # #initialize cannot determine if the call is accepted or not; so if a
# call that's not accepted is used here, the error won't be visible until # call that's not accepted is used here, the error won't be visible until
@ -66,9 +68,9 @@ module Google::RPC
# @param deadline [Fixnum] the deadline for the call to complete # @param deadline [Fixnum] the deadline for the call to complete
# @param finished_tag [Object] the object used as the call's finish tag, # @param finished_tag [Object] the object used as the call's finish tag,
def initialize(call, q, marshal, unmarshal, deadline, finished_tag) def initialize(call, q, marshal, unmarshal, deadline, finished_tag)
raise ArgumentError.new('not a call') unless call.is_a?Core::Call fail(ArgumentError, 'not a call') unless call.is_a? Core::Call
if !q.is_a?Core::CompletionQueue unless q.is_a? Core::CompletionQueue
raise ArgumentError.new('not a CompletionQueue') fail(ArgumentError, 'not a CompletionQueue')
end end
@call = call @call = call
@cq = q @cq = q
@ -110,7 +112,7 @@ module Google::RPC
def run_on_server(gen_each_reply) def run_on_server(gen_each_reply)
replys = gen_each_reply.call(each_queued_msg) replys = gen_each_reply.call(each_queued_msg)
enq_th = start_write_loop(replys, is_client: false) enq_th = start_write_loop(replys, is_client: false)
loop_th = start_read_loop() loop_th = start_read_loop
loop_th.join loop_th.join
enq_th.join enq_th.join
end end
@ -125,7 +127,7 @@ module Google::RPC
# - messages are added to the readq by #read_loop # - messages are added to the readq by #read_loop
# - iteration ends when the instance itself is added # - iteration ends when the instance itself is added
def each_queued_msg def each_queued_msg
return enum_for(:each_queued_msg) if !block_given? return enum_for(:each_queued_msg) unless block_given?
count = 0 count = 0
loop do loop do
logger.debug("each_queued_msg: msg##{count}") logger.debug("each_queued_msg: msg##{count}")
@ -180,8 +182,8 @@ module Google::RPC
end end
# starts the read loop # starts the read loop
def start_read_loop() def start_read_loop
t = Thread.new do Thread.new do
begin begin
read_tag = Object.new read_tag = Object.new
count = 0 count = 0
@ -203,7 +205,7 @@ module Google::RPC
end end
# push the latest read onto the queue and continue reading # push the latest read onto the queue and continue reading
logger.debug("received req.to_s: #{ev.result.to_s}") logger.debug("received req: #{ev.result}")
res = @unmarshal.call(ev.result.to_s) res = @unmarshal.call(ev.result.to_s)
@readq.push(res) @readq.push(res)
ensure ensure
@ -218,7 +220,6 @@ module Google::RPC
end end
end end
end end
end end
end
end end

@ -30,8 +30,9 @@
require 'grpc/generic/active_call' require 'grpc/generic/active_call'
require 'xray/thread_dump_signal_handler' require 'xray/thread_dump_signal_handler'
module Google::RPC module Google
# Google::RPC contains the General RPC module.
module RPC
# ClientStub represents an endpoint used to send requests to GRPC servers. # ClientStub represents an endpoint used to send requests to GRPC servers.
class ClientStub class ClientStub
include Core::StatusCodes include Core::StatusCodes
@ -53,9 +54,9 @@ module Google::RPC
# channel: # channel:
# #
# - :channel_override # - :channel_override
# when present, this must be a pre-created GRPC::Channel. If it's present # when present, this must be a pre-created GRPC::Channel. If it's
# the host and arbitrary keyword arg areignored, and the RPC connection uses # present the host and arbitrary keyword arg areignored, and the RPC
# this channel. # connection uses this channel.
# #
# - :deadline # - :deadline
# when present, this is the default deadline used for calls # when present, this is the default deadline used for calls
@ -69,7 +70,7 @@ module Google::RPC
# @param q [Core::CompletionQueue] used to wait for events # @param q [Core::CompletionQueue] used to wait for events
# @param channel_override [Core::Channel] a pre-created channel # @param channel_override [Core::Channel] a pre-created channel
# @param deadline [Number] the default deadline to use in requests # @param deadline [Number] the default deadline to use in requests
# @param creds [Core::Credentials] secures and/or authenticates the channel # @param creds [Core::Credentials] the channel
# @param update_metadata a func that updates metadata as described above # @param update_metadata a func that updates metadata as described above
# @param kw [KeywordArgs]the channel arguments # @param kw [KeywordArgs]the channel arguments
def initialize(host, q, def initialize(host, q,
@ -78,33 +79,34 @@ module Google::RPC
creds: nil, creds: nil,
update_metadata: nil, update_metadata: nil,
**kw) **kw)
if !q.is_a?Core::CompletionQueue unless q.is_a? Core::CompletionQueue
raise ArgumentError.new('not a CompletionQueue') fail(ArgumentError, 'not a CompletionQueue')
end end
@queue = q @queue = q
# set the channel instance # set the channel instance
if !channel_override.nil? if !channel_override.nil?
ch = channel_override ch = channel_override
raise ArgumentError.new('not a Channel') unless ch.is_a?(Core::Channel) fail(ArgumentError, 'not a Channel') unless ch.is_a? Core::Channel
elsif creds.nil? else
if creds.nil?
ch = Core::Channel.new(host, kw) ch = Core::Channel.new(host, kw)
elsif !creds.is_a?(Core::Credentials) elsif !creds.is_a?(Core::Credentials)
raise ArgumentError.new('not a Credentials') fail(ArgumentError, 'not a Credentials')
else else
ch = Core::Channel.new(host, kw, creds) ch = Core::Channel.new(host, kw, creds)
end end
end
@ch = ch @ch = ch
@update_metadata = nil @update_metadata = nil
if !update_metadata.nil? unless update_metadata.nil?
if !update_metadata.is_a?(Proc) unless update_metadata.is_a? Proc
raise ArgumentError.new('update_metadata is not a Proc') fail(ArgumentError, 'update_metadata is not a Proc')
end end
@update_metadata = update_metadata @update_metadata = update_metadata
end end
@host = host @host = host
@deadline = deadline @deadline = deadline
end end
@ -144,7 +146,7 @@ module Google::RPC
# @param marshal [Function] f(obj)->string that marshals requests # @param marshal [Function] f(obj)->string that marshals requests
# @param unmarshal [Function] f(string)->obj that unmarshals responses # @param unmarshal [Function] f(string)->obj that unmarshals responses
# @param deadline [Numeric] (optional) the max completion time in seconds # @param deadline [Numeric] (optional) the max completion time in seconds
# @param return_op [true|false] (default false) return an Operation if true # @param return_op [true|false] return an Operation if true
# @return [Object] the response received from the server # @return [Object] the response received from the server
def request_response(method, req, marshal, unmarshal, deadline = nil, def request_response(method, req, marshal, unmarshal, deadline = nil,
return_op: false, **kw) return_op: false, **kw)
@ -201,7 +203,7 @@ module Google::RPC
# @param marshal [Function] f(obj)->string that marshals requests # @param marshal [Function] f(obj)->string that marshals requests
# @param unmarshal [Function] f(string)->obj that unmarshals responses # @param unmarshal [Function] f(string)->obj that unmarshals responses
# @param deadline [Numeric] the max completion time in seconds # @param deadline [Numeric] the max completion time in seconds
# @param return_op [true|false] (default false) return an Operation if true # @param return_op [true|false] return an Operation if true
# @return [Object|Operation] the response received from the server # @return [Object|Operation] the response received from the server
def client_streamer(method, requests, marshal, unmarshal, deadline = nil, def client_streamer(method, requests, marshal, unmarshal, deadline = nil,
return_op: false, **kw) return_op: false, **kw)
@ -234,8 +236,8 @@ module Google::RPC
# * the request is sent only when GRPC core's flow control allows it to # * the request is sent only when GRPC core's flow control allows it to
# be sent. # be sent.
# #
# * the request will not complete until the server sends the final response # * the request will not complete until the server sends the final
# followed by a status message. # response followed by a status message.
# #
# == Errors == # == Errors ==
# An RuntimeError is raised if # An RuntimeError is raised if
@ -266,7 +268,7 @@ module Google::RPC
# @param marshal [Function] f(obj)->string that marshals requests # @param marshal [Function] f(obj)->string that marshals requests
# @param unmarshal [Function] f(string)->obj that unmarshals responses # @param unmarshal [Function] f(string)->obj that unmarshals responses
# @param deadline [Numeric] the max completion time in seconds # @param deadline [Numeric] the max completion time in seconds
# @param return_op [true|false] (default false) return an Operation if true # @param return_op [true|false]return an Operation if true
# @param blk [Block] when provided, is executed for each response # @param blk [Block] when provided, is executed for each response
# @return [Enumerator|Operation|nil] as discussed above # @return [Enumerator|Operation|nil] as discussed above
def server_streamer(method, req, marshal, unmarshal, deadline = nil, def server_streamer(method, req, marshal, unmarshal, deadline = nil,
@ -292,10 +294,11 @@ module Google::RPC
# #
# == requests == # == requests ==
# #
# requests provides an 'iterable' of Requests. I.e. it follows Ruby's #each # requests provides an 'iterable' of Requests. I.e. it follows Ruby's
# enumeration protocol. In the simplest case, requests will be an array of # #each enumeration protocol. In the simplest case, requests will be an
# marshallable objects; in typical case it will be an Enumerable that # array of marshallable objects; in typical case it will be an
# allows dynamic construction of the marshallable objects. # Enumerable that allows dynamic construction of the marshallable
# objects.
# #
# == responses == # == responses ==
# #
@ -362,7 +365,8 @@ module Google::RPC
# #
# if return_op is true, the function returns an Operation whose #execute # if return_op is true, the function returns an Operation whose #execute
# method runs the Bidi call. Again, Operation#execute either calls a # method runs the Bidi call. Again, Operation#execute either calls a
# given block with each response or returns an Enumerator of the responses. # given block with each response or returns an Enumerator of the
# responses.
# #
# @param method [String] the RPC method to call on the GRPC server # @param method [String] the RPC method to call on the GRPC server
# @param requests [Object] an Enumerable of requests to send # @param requests [Object] an Enumerable of requests to send
@ -370,7 +374,7 @@ module Google::RPC
# @param unmarshal [Function] f(string)->obj that unmarshals responses # @param unmarshal [Function] f(string)->obj that unmarshals responses
# @param deadline [Numeric] (optional) the max completion time in seconds # @param deadline [Numeric] (optional) the max completion time in seconds
# @param blk [Block] when provided, is executed for each response # @param blk [Block] when provided, is executed for each response
# @param return_op [true|false] (default false) return an Operation if true # @param return_op [true|false] return an Operation if true
# @return [Enumerator|nil|Operation] as discussed above # @return [Enumerator|nil|Operation] as discussed above
def bidi_streamer(method, requests, marshal, unmarshal, deadline = nil, def bidi_streamer(method, requests, marshal, unmarshal, deadline = nil,
return_op: false, **kw, &blk) return_op: false, **kw, &blk)
@ -388,6 +392,7 @@ module Google::RPC
end end
private private
# Creates a new active stub # Creates a new active stub
# #
# @param ch [GRPC::Channel] the channel used to create the stub. # @param ch [GRPC::Channel] the channel used to create the stub.
@ -400,7 +405,6 @@ module Google::RPC
ActiveCall.new(call, @queue, marshal, unmarshal, absolute_deadline, ActiveCall.new(call, @queue, marshal, unmarshal, absolute_deadline,
started: false) started: false)
end end
end end
end
end end

@ -29,8 +29,8 @@
require 'grpc/grpc' require 'grpc/grpc'
module Google::RPC module Google
module RPC
# RpcDesc is a Descriptor of an RPC method. # RpcDesc is a Descriptor of an RPC method.
class RpcDesc < Struct.new(:name, :input, :output, :marshal_method, class RpcDesc < Struct.new(:name, :input, :output, :marshal_method,
:unmarshal_method) :unmarshal_method)
@ -47,7 +47,7 @@ module Google::RPC
# @return [Proc] { |instance| marshalled(instance) } # @return [Proc] { |instance| marshalled(instance) }
def marshal_proc def marshal_proc
Proc.new { |o| o.class.method(marshal_method).call(o).to_s } proc { |o| o.class.method(marshal_method).call(o).to_s }
end end
# @param [:input, :output] target determines whether to produce the an # @param [:input, :output] target determines whether to produce the an
@ -56,27 +56,24 @@ module Google::RPC
# #
# @return [Proc] An unmarshal proc { |marshalled(instance)| instance } # @return [Proc] An unmarshal proc { |marshalled(instance)| instance }
def unmarshal_proc(target) def unmarshal_proc(target)
raise ArgumentError if not [:input, :output].include?(target) fail ArgumentError unless [:input, :output].include?(target)
unmarshal_class = method(target).call unmarshal_class = method(target).call
if unmarshal_class.is_a?Stream unmarshal_class = unmarshal_class.type if unmarshal_class.is_a? Stream
unmarshal_class = unmarshal_class.type proc { |o| unmarshal_class.method(unmarshal_method).call(o) }
end
Proc.new { |o| unmarshal_class.method(unmarshal_method).call(o) }
end end
def run_server_method(active_call, mth) def run_server_method(active_call, mth)
# While a server method is running, it might be cancelled, its deadline # While a server method is running, it might be cancelled, its deadline
# might be reached, the handler could throw an unknown error, or a # might be reached, the handler could throw an unknown error, or a
# well-behaved handler could throw a StatusError. # well-behaved handler could throw a StatusError.
begin if request_response?
if is_request_response?
req = active_call.remote_read req = active_call.remote_read
resp = mth.call(req, active_call.single_req_view) resp = mth.call(req, active_call.single_req_view)
active_call.remote_send(resp) active_call.remote_send(resp)
elsif is_client_streamer? elsif client_streamer?
resp = mth.call(active_call.multi_req_view) resp = mth.call(active_call.multi_req_view)
active_call.remote_send(resp) active_call.remote_send(resp)
elsif is_server_streamer? elsif server_streamer?
req = active_call.remote_read req = active_call.remote_read
replys = mth.call(req, active_call.single_req_view) replys = mth.call(req, active_call.single_req_view)
replys.each { |r| active_call.remote_send(r) } replys.each { |r| active_call.remote_send(r) }
@ -88,7 +85,7 @@ module Google::RPC
rescue BadStatus => e rescue BadStatus => e
# this is raised by handlers that want GRPC to send an application # this is raised by handlers that want GRPC to send an application
# error code and detail message. # error code and detail message.
logger.debug("app error: #{active_call}, status:#{e.code}:#{e.details}") logger.debug("app err: #{active_call}, status:#{e.code}:#{e.details}")
send_status(active_call, e.code, e.details) send_status(active_call, e.code, e.details)
rescue Core::CallError => e rescue Core::CallError => e
# This is raised by GRPC internals but should rarely, if ever happen. # This is raised by GRPC internals but should rarely, if ever happen.
@ -110,33 +107,32 @@ module Google::RPC
logger.warn(e) logger.warn(e)
send_status(active_call, UNKNOWN, 'no reason given') send_status(active_call, UNKNOWN, 'no reason given')
end end
end
def assert_arity_matches(mth) def assert_arity_matches(mth)
if (is_request_response? || is_server_streamer?) if request_response? || server_streamer?
if mth.arity != 2 if mth.arity != 2
raise arity_error(mth, 2, "should be #{mth.name}(req, call)") fail arity_error(mth, 2, "should be #{mth.name}(req, call)")
end end
else else
if mth.arity != 1 if mth.arity != 1
raise arity_error(mth, 1, "should be #{mth.name}(call)") fail arity_error(mth, 1, "should be #{mth.name}(call)")
end end
end end
end end
def is_request_response? def request_response?
!input.is_a?(Stream) && !output.is_a?(Stream) !input.is_a?(Stream) && !output.is_a?(Stream)
end end
def is_client_streamer? def client_streamer?
input.is_a?(Stream) && !output.is_a?(Stream) input.is_a?(Stream) && !output.is_a?(Stream)
end end
def is_server_streamer? def server_streamer?
!input.is_a?(Stream) && output.is_a?(Stream) !input.is_a?(Stream) && output.is_a?(Stream)
end end
def is_bidi_streamer? def bidi_streamer?
input.is_a?(Stream) && output.is_a?(Stream) input.is_a?(Stream) && output.is_a?(Stream)
end end
@ -145,15 +141,12 @@ module Google::RPC
end end
def send_status(active_client, code, details) def send_status(active_client, code, details)
begin
details = 'Not sure why' if details.nil? details = 'Not sure why' if details.nil?
active_client.send_status(code, details) active_client.send_status(code, details)
rescue StandardError => e rescue StandardError => e
logger.warn('Could not send status %d:%s' % [code, details]) logger.warn("Could not send status #{code}:#{details}")
logger.warn(e) logger.warn(e)
end end
end end
end end
end end

@ -33,8 +33,9 @@ require 'grpc/generic/service'
require 'thread' require 'thread'
require 'xray/thread_dump_signal_handler' require 'xray/thread_dump_signal_handler'
module Google::RPC module Google
# Google::RPC contains the General RPC module.
module RPC
# RpcServer hosts a number of services and makes them available on the # RpcServer hosts a number of services and makes them available on the
# network. # network.
class RpcServer class RpcServer
@ -84,26 +85,28 @@ module Google::RPC
creds:nil, creds:nil,
server_override:nil, server_override:nil,
**kw) **kw)
if !completion_queue_override.nil? if completion_queue_override.nil?
cq = Core::CompletionQueue.new
else
cq = completion_queue_override cq = completion_queue_override
if !cq.is_a?(Core::CompletionQueue) unless cq.is_a? Core::CompletionQueue
raise ArgumentError.new('not a CompletionQueue') fail(ArgumentError, 'not a CompletionQueue')
end end
else
cq = Core::CompletionQueue.new
end end
@cq = cq @cq = cq
if !server_override.nil? if server_override.nil?
srv = server_override if creds.nil?
raise ArgumentError.new('not a Server') unless srv.is_a?(Core::Server)
elsif creds.nil?
srv = Core::Server.new(@cq, kw) srv = Core::Server.new(@cq, kw)
elsif !creds.is_a?(Core::ServerCredentials) elsif !creds.is_a? Core::ServerCredentials
raise ArgumentError.new('not a ServerCredentials') fail(ArgumentError, 'not a ServerCredentials')
else else
srv = Core::Server.new(@cq, kw, creds) srv = Core::Server.new(@cq, kw, creds)
end end
else
srv = server_override
fail(ArgumentError, 'not a Server') unless srv.is_a? Core::Server
end
@server = srv @server = srv
@pool_size = pool_size @pool_size = pool_size
@ -119,11 +122,10 @@ module Google::RPC
# the call has no impact if the server is already stopped, otherwise # the call has no impact if the server is already stopped, otherwise
# server's current call loop is it's last. # server's current call loop is it's last.
def stop def stop
if @running return unless @running
@stopped = true @stopped = true
@pool.stop @pool.stop
end end
end
# determines if the server is currently running # determines if the server is currently running
def running? def running?
@ -139,12 +141,10 @@ module Google::RPC
def wait_till_running(timeout = 0.1) def wait_till_running(timeout = 0.1)
end_time, sleep_period = Time.now + timeout, (1.0 * timeout) / 100 end_time, sleep_period = Time.now + timeout, (1.0 * timeout) / 100
while Time.now < end_time while Time.now < end_time
if !running? @run_mutex.synchronize { @run_cond.wait(@run_mutex) } unless running?
@run_mutex.synchronize { @run_cond.wait(@run_mutex) }
end
sleep(sleep_period) sleep(sleep_period)
end end
return running? running?
end end
# determines if the server is currently stopped # determines if the server is currently stopped
@ -179,14 +179,14 @@ module Google::RPC
# #
# It raises RuntimeError: # It raises RuntimeError:
# - if service is not valid service class or object # - if service is not valid service class or object
# - if it is a valid service, but the handler methods are already registered # - its handler methods are already registered
# - if the server is already running # - if the server is already running
# #
# @param service [Object|Class] a service class or object as described # @param service [Object|Class] a service class or object as described
# above # above
def handle(service) def handle(service)
raise 'cannot add services if the server is running' if running? fail 'cannot add services if the server is running' if running?
raise 'cannot add services if the server is stopped' if stopped? fail 'cannot add services if the server is stopped' if stopped?
cls = service.is_a?(Class) ? service : service.class cls = service.is_a?(Class) ? service : service.class
assert_valid_service_class(cls) assert_valid_service_class(cls)
add_rpc_descs_for(service) add_rpc_descs_for(service)
@ -211,7 +211,7 @@ module Google::RPC
@pool.start @pool.start
@server.start @server.start
server_tag = Object.new server_tag = Object.new
while !stopped? until stopped?
@server.request_call(server_tag) @server.request_call(server_tag)
ev = @cq.pluck(server_tag, @poll_period) ev = @cq.pluck(server_tag, @poll_period)
next if ev.nil? next if ev.nil?
@ -221,7 +221,7 @@ module Google::RPC
next next
end end
c = new_active_server_call(ev.call, ev.result) c = new_active_server_call(ev.call, ev.result)
if !c.nil? unless c.nil?
mth = ev.result.method.to_sym mth = ev.result.method.to_sym
ev.close ev.close
@pool.schedule(c) do |call| @pool.schedule(c) do |call|
@ -233,37 +233,39 @@ module Google::RPC
end end
def new_active_server_call(call, new_server_rpc) def new_active_server_call(call, new_server_rpc)
# TODO(temiola): perhaps reuse the main server completion queue here, but # TODO(temiola): perhaps reuse the main server completion queue here,
# for now, create a new completion queue per call, pending best practice # but for now, create a new completion queue per call, pending best
# usage advice from the c core. # practice usage advice from the c core.
# Accept the call. This is necessary even if a status is to be sent back # Accept the call. This is necessary even if a status is to be sent
# immediately # back immediately
finished_tag = Object.new finished_tag = Object.new
call_queue = Core::CompletionQueue.new call_queue = Core::CompletionQueue.new
call.metadata = new_server_rpc.metadata # store the metadata on the call call.metadata = new_server_rpc.metadata # store the metadata
call.server_accept(call_queue, finished_tag) call.server_accept(call_queue, finished_tag)
call.server_end_initial_metadata() call.server_end_initial_metadata
# Send UNAVAILABLE if there are too many unprocessed jobs # Send UNAVAILABLE if there are too many unprocessed jobs
jobs_count, max = @pool.jobs_waiting, @max_waiting_requests jobs_count, max = @pool.jobs_waiting, @max_waiting_requests
logger.info("waiting: #{jobs_count}, max: #{max}") logger.info("waiting: #{jobs_count}, max: #{max}")
if @pool.jobs_waiting > @max_waiting_requests if @pool.jobs_waiting > @max_waiting_requests
logger.warn("NOT AVAILABLE: too many jobs_waiting: #{new_server_rpc}") logger.warn("NOT AVAILABLE: too many jobs_waiting: #{new_server_rpc}")
noop = Proc.new { |x| x } noop = proc { |x| x }
c = ActiveCall.new(call, call_queue, noop, noop, c = ActiveCall.new(call, call_queue, noop, noop,
new_server_rpc.deadline, finished_tag: finished_tag) new_server_rpc.deadline,
finished_tag: finished_tag)
c.send_status(StatusCodes::UNAVAILABLE, '') c.send_status(StatusCodes::UNAVAILABLE, '')
return nil return nil
end end
# Send NOT_FOUND if the method does not exist # Send NOT_FOUND if the method does not exist
mth = new_server_rpc.method.to_sym mth = new_server_rpc.method.to_sym
if !rpc_descs.has_key?(mth) unless rpc_descs.key?(mth)
logger.warn("NOT_FOUND: #{new_server_rpc}") logger.warn("NOT_FOUND: #{new_server_rpc}")
noop = Proc.new { |x| x } noop = proc { |x| x }
c = ActiveCall.new(call, call_queue, noop, noop, c = ActiveCall.new(call, call_queue, noop, noop,
new_server_rpc.deadline, finished_tag: finished_tag) new_server_rpc.deadline,
finished_tag: finished_tag)
c.send_status(StatusCodes::NOT_FOUND, '') c.send_status(StatusCodes::NOT_FOUND, '')
return nil return nil
end end
@ -278,9 +280,8 @@ module Google::RPC
# Pool is a simple thread pool for running server requests. # Pool is a simple thread pool for running server requests.
class Pool class Pool
def initialize(size) def initialize(size)
raise 'pool size must be positive' unless size > 0 fail 'pool size must be positive' unless size > 0
@jobs = Queue.new @jobs = Queue.new
@size = size @size = size
@stopped = false @stopped = false
@ -299,7 +300,7 @@ module Google::RPC
# @param args the args passed blk when it is called # @param args the args passed blk when it is called
# @param blk the block to call # @param blk the block to call
def schedule(*args, &blk) def schedule(*args, &blk)
raise 'already stopped' if @stopped fail 'already stopped' if @stopped
return if blk.nil? return if blk.nil?
logger.info('schedule another job') logger.info('schedule another job')
@jobs << [blk, args] @jobs << [blk, args]
@ -307,7 +308,7 @@ module Google::RPC
# Starts running the jobs in the thread pool. # Starts running the jobs in the thread pool.
def start def start
raise 'already stopped' if @stopped fail 'already stopped' if @stopped
until @workers.size == @size.to_i until @workers.size == @size.to_i
next_thread = Thread.new do next_thread = Thread.new do
catch(:exit) do # allows { throw :exit } to kill a thread catch(:exit) do # allows { throw :exit } to kill a thread
@ -322,13 +323,11 @@ module Google::RPC
end end
end end
# removes the threads from workers, and signal when all the threads # removes the threads from workers, and signal when all the
# are complete. # threads are complete.
@stop_mutex.synchronize do @stop_mutex.synchronize do
@workers.delete(Thread.current) @workers.delete(Thread.current)
if @workers.size == 0 @stop_cond.signal if @workers.size == 0
@stop_cond.signal
end
end end
end end
@workers << next_thread @workers << next_thread
@ -344,9 +343,7 @@ module Google::RPC
# TODO(temiola): allow configuration of the keepalive period # TODO(temiola): allow configuration of the keepalive period
keep_alive = 5 keep_alive = 5
@stop_mutex.synchronize do @stop_mutex.synchronize do
if @workers.size > 0 @stop_cond.wait(@stop_mutex, keep_alive) if @workers.size > 0
@stop_cond.wait(@stop_mutex, keep_alive)
end
end end
# Forcibly shutdown any threads that are still alive. # Forcibly shutdown any threads that are still alive.
@ -365,7 +362,6 @@ module Google::RPC
logger.info('stopped, all workers are shutdown') logger.info('stopped, all workers are shutdown')
end end
end end
protected protected
@ -381,11 +377,11 @@ module Google::RPC
private private
def assert_valid_service_class(cls) def assert_valid_service_class(cls)
if !cls.include?(GenericService) unless cls.include?(GenericService)
raise "#{cls} should 'include GenericService'" fail "#{cls} should 'include GenericService'"
end end
if cls.rpc_descs.size == 0 if cls.rpc_descs.size == 0
raise "#{cls} should specify some rpc descriptions" fail "#{cls} should specify some rpc descriptions"
end end
cls.assert_rpc_descs_have_methods cls.assert_rpc_descs_have_methods
end end
@ -396,8 +392,8 @@ module Google::RPC
handlers = rpc_handlers handlers = rpc_handlers
cls.rpc_descs.each_pair do |name, spec| cls.rpc_descs.each_pair do |name, spec|
route = "/#{cls.service_name}/#{name}".to_sym route = "/#{cls.service_name}/#{name}".to_sym
if specs.has_key?(route) if specs.key? route
raise "Cannot add rpc #{route} from #{spec}, already registered" fail "Cannot add rpc #{route} from #{spec}, already registered"
else else
specs[route] = spec specs[route] = spec
if service.is_a?(Class) if service.is_a?(Class)
@ -410,5 +406,5 @@ module Google::RPC
end end
end end
end end
end
end end

@ -32,7 +32,6 @@ require 'grpc/generic/rpc_desc'
# Extend String to add a method underscore # Extend String to add a method underscore
class String class String
# creates a new string that is the underscore separate version of this one. # creates a new string that is the underscore separate version of this one.
# #
# E.g, # E.g,
@ -40,24 +39,23 @@ class String
# AMethod -> a_method # AMethod -> a_method
# AnRpc -> an_rpc # AnRpc -> an_rpc
def underscore def underscore
word = self.dup word = dup
word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2') word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
word.tr!('-', '_') word.tr!('-', '_')
word.downcase! word.downcase!
word word
end end
end end
module Google::RPC module Google
# Google::RPC contains the General RPC module.
module RPC
# Provides behaviour used to implement schema-derived service classes. # Provides behaviour used to implement schema-derived service classes.
# #
# Is intended to be used to support both client and server IDL-schema-derived # Is intended to be used to support both client and server
# servers. # IDL-schema-derived servers.
module GenericService module GenericService
# Used to indicate that a name has already been specified # Used to indicate that a name has already been specified
class DuplicateRpcName < StandardError class DuplicateRpcName < StandardError
def initialize(name) def initialize(name)
@ -80,7 +78,6 @@ module Google::RPC
# #assert_rpc_descs_have_methods is used to ensure the including class # #assert_rpc_descs_have_methods is used to ensure the including class
# provides methods with signatures that support all the descriptors. # provides methods with signatures that support all the descriptors.
module Dsl module Dsl
# This configures the method names that the serializable message # This configures the method names that the serializable message
# implementation uses to marshal and unmarshal messages. # implementation uses to marshal and unmarshal messages.
# #
@ -110,7 +107,7 @@ module Google::RPC
# @param input [Object] the input parameter's class # @param input [Object] the input parameter's class
# @param output [Object] the output parameter's class # @param output [Object] the output parameter's class
def rpc(name, input, output) def rpc(name, input, output)
raise DuplicateRpcName, name if rpc_descs.has_key?(name) fail(DuplicateRpcName, name) if rpc_descs.key? name
assert_can_marshal(input) assert_can_marshal(input)
assert_can_marshal(output) assert_can_marshal(output)
rpc_descs[name] = RpcDesc.new(name, input, output, rpc_descs[name] = RpcDesc.new(name, input, output,
@ -125,7 +122,8 @@ module Google::RPC
subclass.service_name = service_name subclass.service_name = service_name
end end
# the name of the instance method used to marshal events to a byte stream. # the name of the instance method used to marshal events to a byte
# stream.
def marshal_class_method def marshal_class_method
@marshal_class_method ||= :marshal @marshal_class_method ||= :marshal
end end
@ -136,19 +134,14 @@ module Google::RPC
end end
def assert_can_marshal(cls) def assert_can_marshal(cls)
if cls.is_a?RpcDesc::Stream cls = cls.type if cls.is_a? RpcDesc::Stream
cls = cls.type
end
mth = unmarshal_class_method mth = unmarshal_class_method
if !cls.methods.include?(mth) unless cls.methods.include? mth
raise ArgumentError, "#{cls} needs #{cls}.#{mth}" fail(ArgumentError, "#{cls} needs #{cls}.#{mth}")
end end
mth = marshal_class_method mth = marshal_class_method
if !cls.methods.include?(mth) return if cls.methods.include? mth
raise ArgumentError, "#{cls} needs #{cls}.#{mth}" fail(ArgumentError, "#{cls} needs #{cls}.#{mth}")
end
end end
# @param cls [Class] the class of a serializable type # @param cls [Class] the class of a serializable type
@ -169,7 +162,6 @@ module Google::RPC
descs = rpc_descs descs = rpc_descs
route_prefix = service_name route_prefix = service_name
Class.new(ClientStub) do Class.new(ClientStub) do
# @param host [String] the host the stub connects to # @param host [String] the host the stub connects to
# @param kw [KeywordArgs] the channel arguments, plus any optional # @param kw [KeywordArgs] the channel arguments, plus any optional
# args for configuring the client's channel # args for configuring the client's channel
@ -184,20 +176,21 @@ module Google::RPC
marshal = desc.marshal_proc marshal = desc.marshal_proc
unmarshal = desc.unmarshal_proc(:output) unmarshal = desc.unmarshal_proc(:output)
route = "/#{route_prefix}/#{name}" route = "/#{route_prefix}/#{name}"
if desc.is_request_response? if desc.request_response?
define_method(mth_name) do |req, deadline = nil| define_method(mth_name) do |req, deadline = nil|
logger.debug("calling #{@host}:#{route}") logger.debug("calling #{@host}:#{route}")
request_response(route, req, marshal, unmarshal, deadline) request_response(route, req, marshal, unmarshal, deadline)
end end
elsif desc.is_client_streamer? elsif desc.client_streamer?
define_method(mth_name) do |reqs, deadline = nil| define_method(mth_name) do |reqs, deadline = nil|
logger.debug("calling #{@host}:#{route}") logger.debug("calling #{@host}:#{route}")
client_streamer(route, reqs, marshal, unmarshal, deadline) client_streamer(route, reqs, marshal, unmarshal, deadline)
end end
elsif desc.is_server_streamer? elsif desc.server_streamer?
define_method(mth_name) do |req, deadline = nil, &blk| define_method(mth_name) do |req, deadline = nil, &blk|
logger.debug("calling #{@host}:#{route}") logger.debug("calling #{@host}:#{route}")
server_streamer(route, req, marshal, unmarshal, deadline, &blk) server_streamer(route, req, marshal, unmarshal, deadline,
&blk)
end end
else # is a bidi_stream else # is a bidi_stream
define_method(mth_name) do |reqs, deadline = nil, &blk| define_method(mth_name) do |reqs, deadline = nil, &blk|
@ -206,9 +199,7 @@ module Google::RPC
end end
end end
end end
end end
end end
# Asserts that the appropriate methods are defined for each added rpc # Asserts that the appropriate methods are defined for each added rpc
@ -217,18 +208,16 @@ module Google::RPC
def assert_rpc_descs_have_methods def assert_rpc_descs_have_methods
rpc_descs.each_pair do |m, spec| rpc_descs.each_pair do |m, spec|
mth_name = m.to_s.underscore.to_sym mth_name = m.to_s.underscore.to_sym
if !self.instance_methods.include?(mth_name) unless instance_methods.include?(mth_name)
raise "#{self} does not provide instance method '#{mth_name}'" fail "#{self} does not provide instance method '#{mth_name}'"
end end
spec.assert_arity_matches(self.instance_method(mth_name)) spec.assert_arity_matches(instance_method(mth_name))
end end
end end
end end
def self.included(o) def self.included(o)
o.extend(Dsl) o.extend(Dsl)
# Update to the use the service name including module. Proivde a default # Update to the use the service name including module. Proivde a default
# that can be nil e,g. when modules are declared dynamically. # that can be nil e,g. when modules are declared dynamically.
return unless o.service_name.nil? return unless o.service_name.nil?
@ -243,7 +232,6 @@ module Google::RPC
end end
end end
end end
end end
end
end end

@ -28,6 +28,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
module Google module Google
# Google::RPC contains the General RPC module.
module RPC module RPC
VERSION = '0.0.1' VERSION = '0.0.1'
end end

@ -30,7 +30,6 @@
require 'grpc' require 'grpc'
describe 'Wrapped classes where .new cannot create an instance' do describe 'Wrapped classes where .new cannot create an instance' do
describe GRPC::Core::Event do describe GRPC::Core::Event do
it 'should fail .new fail with a runtime error' do it 'should fail .new fail with a runtime error' do
expect { GRPC::Core::Event.new }.to raise_error(TypeError) expect { GRPC::Core::Event.new }.to raise_error(TypeError)
@ -42,5 +41,4 @@ describe 'Wrapped classes where .new cannot create an instance' do
expect { GRPC::Core::Event.new }.to raise_error(TypeError) expect { GRPC::Core::Event.new }.to raise_error(TypeError)
end end
end end
end end

@ -30,9 +30,7 @@
require 'grpc' require 'grpc'
describe GRPC::Core::ByteBuffer do describe GRPC::Core::ByteBuffer do
describe '#new' do describe '#new' do
it 'is constructed from a string' do it 'is constructed from a string' do
expect { GRPC::Core::ByteBuffer.new('#new') }.not_to raise_error expect { GRPC::Core::ByteBuffer.new('#new') }.not_to raise_error
end end
@ -50,7 +48,6 @@ describe GRPC::Core::ByteBuffer do
expect { GRPC::Core::ByteBuffer.new(x) }.to raise_error TypeError expect { GRPC::Core::ByteBuffer.new(x) }.to raise_error TypeError
end end
end end
end end
describe '#to_s' do describe '#to_s' do
@ -67,5 +64,4 @@ describe GRPC::Core::ByteBuffer do
expect(a_copy.dup.to_s).to eq('#dup') expect(a_copy.dup.to_s).to eq('#dup')
end end
end end
end end

@ -33,20 +33,19 @@ require 'port_picker'
include GRPC::Core::StatusCodes include GRPC::Core::StatusCodes
describe GRPC::Core::RpcErrors do describe GRPC::Core::RpcErrors do
before(:each) do before(:each) do
@known_types = { @known_types = {
:OK => 0, OK: 0,
:ERROR => 1, ERROR: 1,
:NOT_ON_SERVER => 2, NOT_ON_SERVER: 2,
:NOT_ON_CLIENT => 3, NOT_ON_CLIENT: 3,
:ALREADY_ACCEPTED => 4, ALREADY_ACCEPTED: 4,
:ALREADY_INVOKED => 5, ALREADY_INVOKED: 5,
:NOT_INVOKED => 6, NOT_INVOKED: 6,
:ALREADY_FINISHED => 7, ALREADY_FINISHED: 7,
:TOO_MANY_OPERATIONS => 8, TOO_MANY_OPERATIONS: 8,
:INVALID_FLAGS => 9, INVALID_FLAGS: 9,
:ErrorMessages => { ErrorMessages: {
0 => 'ok', 0 => 'ok',
1 => 'unknown error', 1 => 'unknown error',
2 => 'not available on a server', 2 => 'not available on a server',
@ -56,7 +55,7 @@ describe GRPC::Core::RpcErrors do
6 => 'call is not yet invoked', 6 => 'call is not yet invoked',
7 => 'call is already finished', 7 => 'call is already finished',
8 => 'outstanding read or write present', 8 => 'outstanding read or write present',
9=>'a bad flag was given', 9 => 'a bad flag was given'
} }
} }
end end
@ -66,11 +65,9 @@ describe GRPC::Core::RpcErrors do
syms_and_codes = m.constants.collect { |c| [c, m.const_get(c)] } syms_and_codes = m.constants.collect { |c| [c, m.const_get(c)] }
expect(Hash[syms_and_codes]).to eq(@known_types) expect(Hash[syms_and_codes]).to eq(@known_types)
end end
end end
describe GRPC::Core::Call do describe GRPC::Core::Call do
before(:each) do before(:each) do
@tag = Object.new @tag = Object.new
@client_queue = GRPC::Core::CompletionQueue.new @client_queue = GRPC::Core::CompletionQueue.new
@ -88,7 +85,7 @@ describe GRPC::Core::Call do
describe '#start_read' do describe '#start_read' do
it 'should fail if called immediately' do it 'should fail if called immediately' do
blk = Proc.new { make_test_call.start_read(@tag) } blk = proc { make_test_call.start_read(@tag) }
expect(&blk).to raise_error GRPC::Core::CallError expect(&blk).to raise_error GRPC::Core::CallError
end end
end end
@ -96,21 +93,21 @@ describe GRPC::Core::Call do
describe '#start_write' do describe '#start_write' do
it 'should fail if called immediately' do it 'should fail if called immediately' do
bytes = GRPC::Core::ByteBuffer.new('test string') bytes = GRPC::Core::ByteBuffer.new('test string')
blk = Proc.new { make_test_call.start_write(bytes, @tag) } blk = proc { make_test_call.start_write(bytes, @tag) }
expect(&blk).to raise_error GRPC::Core::CallError expect(&blk).to raise_error GRPC::Core::CallError
end end
end end
describe '#start_write_status' do describe '#start_write_status' do
it 'should fail if called immediately' do it 'should fail if called immediately' do
blk = Proc.new { make_test_call.start_write_status(153, 'x', @tag) } blk = proc { make_test_call.start_write_status(153, 'x', @tag) }
expect(&blk).to raise_error GRPC::Core::CallError expect(&blk).to raise_error GRPC::Core::CallError
end end
end end
describe '#writes_done' do describe '#writes_done' do
it 'should fail if called immediately' do it 'should fail if called immediately' do
blk = Proc.new { make_test_call.writes_done(Object.new) } blk = proc { make_test_call.writes_done(Object.new) }
expect(&blk).to raise_error GRPC::Core::CallError expect(&blk).to raise_error GRPC::Core::CallError
end end
end end
@ -119,7 +116,8 @@ describe GRPC::Core::Call do
it 'adds metadata to a call without fail' do it 'adds metadata to a call without fail' do
call = make_test_call call = make_test_call
n = 37 n = 37
metadata = Hash[n.times.collect { |i| ["key%d" % i, "value%d" %i] } ] one_md = proc { |x| [sprintf('key%d', x), sprintf('value%d', x)] }
metadata = Hash[n.times.collect { |i| one_md.call i }]
expect { call.add_metadata(metadata) }.to_not raise_error expect { call.add_metadata(metadata) }.to_not raise_error
end end
end end
@ -191,7 +189,6 @@ describe GRPC::Core::Call do
end end
end end
def make_test_call def make_test_call
@ch.create_call('dummy_method', 'dummy_host', deadline) @ch.create_call('dummy_method', 'dummy_host', deadline)
end end
@ -199,5 +196,4 @@ describe GRPC::Core::Call do
def deadline def deadline
Time.now + 2 # in 2 seconds; arbitrary Time.now + 2 # in 2 seconds; arbitrary
end end
end end

@ -37,8 +37,6 @@ def load_test_certs
end end
describe GRPC::Core::Channel do describe GRPC::Core::Channel do
def create_test_cert def create_test_cert
GRPC::Core::Credentials.new(load_test_certs[0]) GRPC::Core::Credentials.new(load_test_certs[0])
end end
@ -48,7 +46,6 @@ describe GRPC::Core::Channel do
end end
shared_examples '#new' do shared_examples '#new' do
it 'take a host name without channel args' do it 'take a host name without channel args' do
expect { GRPC::Core::Channel.new('dummy_host', nil) }.not_to raise_error expect { GRPC::Core::Channel.new('dummy_host', nil) }.not_to raise_error
end end
@ -61,14 +58,14 @@ describe GRPC::Core::Channel do
end end
it 'does not take a hash with bad values as channel args' do it 'does not take a hash with bad values as channel args' do
blk = construct_with_args(:symbol => Object.new) blk = construct_with_args(symbol: Object.new)
expect(&blk).to raise_error TypeError expect(&blk).to raise_error TypeError
blk = construct_with_args('1' => Hash.new) blk = construct_with_args('1' => Hash.new)
expect(&blk).to raise_error TypeError expect(&blk).to raise_error TypeError
end end
it 'can take a hash with a symbol key as channel args' do it 'can take a hash with a symbol key as channel args' do
blk = construct_with_args(:a_symbol => 1) blk = construct_with_args(a_symbol: 1)
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
@ -78,17 +75,17 @@ describe GRPC::Core::Channel do
end end
it 'can take a hash with a string value as channel args' do it 'can take a hash with a string value as channel args' do
blk = construct_with_args(:a_symbol => '1') blk = construct_with_args(a_symbol: '1')
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
it 'can take a hash with a symbol value as channel args' do it 'can take a hash with a symbol value as channel args' do
blk = construct_with_args(:a_symbol => :another_symbol) blk = construct_with_args(a_symbol: :another_symbol)
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
it 'can take a hash with a numeric value as channel args' do it 'can take a hash with a numeric value as channel args' do
blk = construct_with_args(:a_symbol => 1) blk = construct_with_args(a_symbol: 1)
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
@ -97,13 +94,11 @@ describe GRPC::Core::Channel do
blk = construct_with_args(args) blk = construct_with_args(args)
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
end end
describe '#new for secure channels' do describe '#new for secure channels' do
def construct_with_args(a) def construct_with_args(a)
Proc.new { GRPC::Core::Channel.new('dummy_host', a, create_test_cert) } proc { GRPC::Core::Channel.new('dummy_host', a, create_test_cert) }
end end
it_behaves_like '#new' it_behaves_like '#new'
@ -113,7 +108,7 @@ describe GRPC::Core::Channel do
it_behaves_like '#new' it_behaves_like '#new'
def construct_with_args(a) def construct_with_args(a)
Proc.new { GRPC::Core::Channel.new('dummy_host', a) } proc { GRPC::Core::Channel.new('dummy_host', a) }
end end
end end
@ -125,7 +120,7 @@ describe GRPC::Core::Channel do
deadline = Time.now + 5 deadline = Time.now + 5
blk = Proc.new do blk = proc do
ch.create_call('dummy_method', 'dummy_host', deadline) ch.create_call('dummy_method', 'dummy_host', deadline)
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -138,12 +133,11 @@ describe GRPC::Core::Channel do
ch.close ch.close
deadline = Time.now + 5 deadline = Time.now + 5
blk = Proc.new do blk = proc do
ch.create_call('dummy_method', 'dummy_host', deadline) ch.create_call('dummy_method', 'dummy_host', deadline)
end end
expect(&blk).to raise_error(RuntimeError) expect(&blk).to raise_error(RuntimeError)
end end
end end
describe '#destroy' do describe '#destroy' do
@ -151,7 +145,7 @@ describe GRPC::Core::Channel do
port = find_unused_tcp_port port = find_unused_tcp_port
host = "localhost:#{port}" host = "localhost:#{port}"
ch = GRPC::Core::Channel.new(host, nil) ch = GRPC::Core::Channel.new(host, nil)
blk = Proc.new { ch.destroy } blk = proc { ch.destroy }
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
@ -159,18 +153,16 @@ describe GRPC::Core::Channel do
port = find_unused_tcp_port port = find_unused_tcp_port
host = "localhost:#{port}" host = "localhost:#{port}"
ch = GRPC::Core::Channel.new(host, nil) ch = GRPC::Core::Channel.new(host, nil)
blk = Proc.new { ch.destroy } blk = proc { ch.destroy }
blk.call blk.call
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
end end
describe '::SSL_TARGET' do describe '::SSL_TARGET' do
it 'is a symbol' do it 'is a symbol' do
expect(GRPC::Core::Channel::SSL_TARGET).to be_a(Symbol) expect(GRPC::Core::Channel::SSL_TARGET).to be_a(Symbol)
end end
end end
describe '#close' do describe '#close' do
@ -178,7 +170,7 @@ describe GRPC::Core::Channel do
port = find_unused_tcp_port port = find_unused_tcp_port
host = "localhost:#{port}" host = "localhost:#{port}"
ch = GRPC::Core::Channel.new(host, nil) ch = GRPC::Core::Channel.new(host, nil)
blk = Proc.new { ch.close } blk = proc { ch.close }
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
@ -186,10 +178,9 @@ describe GRPC::Core::Channel do
port = find_unused_tcp_port port = find_unused_tcp_port
host = "localhost:#{port}" host = "localhost:#{port}"
ch = GRPC::Core::Channel.new(host, nil) ch = GRPC::Core::Channel.new(host, nil)
blk = Proc.new { ch.close } blk = proc { ch.close }
blk.call blk.call
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
end end
end end

@ -41,7 +41,6 @@ def load_test_certs
end end
shared_context 'setup: tags' do shared_context 'setup: tags' do
before(:example) do before(:example) do
@server_finished_tag = Object.new @server_finished_tag = Object.new
@client_finished_tag = Object.new @client_finished_tag = Object.new
@ -71,7 +70,7 @@ shared_context 'setup: tags' do
expect(ev).not_to be_nil expect(ev).not_to be_nil
expect(ev.type).to be(SERVER_RPC_NEW) expect(ev.type).to be(SERVER_RPC_NEW)
ev.call.server_accept(@server_queue, @server_finished_tag) ev.call.server_accept(@server_queue, @server_finished_tag)
ev.call.server_end_initial_metadata() ev.call.server_end_initial_metadata
ev.call.start_read(@server_tag) ev.call.start_read(@server_tag)
ev = @server_queue.pluck(@server_tag, TimeConsts::INFINITE_FUTURE) ev = @server_queue.pluck(@server_tag, TimeConsts::INFINITE_FUTURE)
expect(ev.type).to be(READ) expect(ev.type).to be(READ)
@ -79,7 +78,7 @@ shared_context 'setup: tags' do
ev = @server_queue.pluck(@server_tag, TimeConsts::INFINITE_FUTURE) ev = @server_queue.pluck(@server_tag, TimeConsts::INFINITE_FUTURE)
expect(ev).not_to be_nil expect(ev).not_to be_nil
expect(ev.type).to be(WRITE_ACCEPTED) expect(ev.type).to be(WRITE_ACCEPTED)
return ev.call ev.call
end end
def client_sends(call, sent = 'a message') def client_sends(call, sent = 'a message')
@ -92,17 +91,15 @@ shared_context 'setup: tags' do
ev = @client_queue.pluck(@tag, TimeConsts::INFINITE_FUTURE) ev = @client_queue.pluck(@tag, TimeConsts::INFINITE_FUTURE)
expect(ev).not_to be_nil expect(ev).not_to be_nil
expect(ev.type).to be(WRITE_ACCEPTED) expect(ev.type).to be(WRITE_ACCEPTED)
return sent sent
end end
def new_client_call def new_client_call
@ch.create_call('/method', 'localhost', deadline) @ch.create_call('/method', 'localhost', deadline)
end end
end end
shared_examples 'basic GRPC message delivery is OK' do shared_examples 'basic GRPC message delivery is OK' do
include_context 'setup: tags' include_context 'setup: tags'
it 'servers receive requests from clients and start responding' do it 'servers receive requests from clients and start responding' do
@ -126,7 +123,7 @@ shared_examples 'basic GRPC message delivery is OK' do
# the server response # the server response
server_call.start_write(reply, @server_tag) server_call.start_write(reply, @server_tag)
ev = expect_next_event_on(@server_queue, WRITE_ACCEPTED, @server_tag) expect_next_event_on(@server_queue, WRITE_ACCEPTED, @server_tag)
end end
it 'responses written by servers are received by the client' do it 'responses written by servers are received by the client' do
@ -135,15 +132,14 @@ shared_examples 'basic GRPC message delivery is OK' do
server_receives_and_responds_with('server_response') server_receives_and_responds_with('server_response')
call.start_read(@tag) call.start_read(@tag)
ev = expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag) expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag)
ev = expect_next_event_on(@client_queue, READ, @tag) ev = expect_next_event_on(@client_queue, READ, @tag)
expect(ev.result.to_s).to eq('server_response') expect(ev.result.to_s).to eq('server_response')
end end
it 'servers can ignore a client write and send a status' do it 'servers can ignore a client write and send a status' do
reply = ByteBuffer.new('the server payload')
call = new_client_call call = new_client_call
msg = client_sends(call) client_sends(call)
# check the server rpc new was received # check the server rpc new was received
@server.request_call(@server_tag) @server.request_call(@server_tag)
@ -153,20 +149,20 @@ shared_examples 'basic GRPC message delivery is OK' do
# accept the call - need to do this to sent status. # accept the call - need to do this to sent status.
server_call = ev.call server_call = ev.call
server_call.server_accept(@server_queue, @server_finished_tag) server_call.server_accept(@server_queue, @server_finished_tag)
server_call.server_end_initial_metadata() server_call.server_end_initial_metadata
server_call.start_write_status(StatusCodes::NOT_FOUND, 'not found', server_call.start_write_status(StatusCodes::NOT_FOUND, 'not found',
@server_tag) @server_tag)
# client gets an empty response for the read, preceeded by some metadata. # client gets an empty response for the read, preceeded by some metadata.
call.start_read(@tag) call.start_read(@tag)
ev = expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag) expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag)
ev = expect_next_event_on(@client_queue, READ, @tag) ev = expect_next_event_on(@client_queue, READ, @tag)
expect(ev.tag).to be(@tag) expect(ev.tag).to be(@tag)
expect(ev.result.to_s).to eq('') expect(ev.result.to_s).to eq('')
# finally, after client sends writes_done, they get the finished. # finally, after client sends writes_done, they get the finished.
call.writes_done(@tag) call.writes_done(@tag)
ev = expect_next_event_on(@client_queue, FINISH_ACCEPTED, @tag) expect_next_event_on(@client_queue, FINISH_ACCEPTED, @tag)
ev = expect_next_event_on(@client_queue, FINISHED, @client_finished_tag) ev = expect_next_event_on(@client_queue, FINISHED, @client_finished_tag)
expect(ev.result.code).to eq(StatusCodes::NOT_FOUND) expect(ev.result.code).to eq(StatusCodes::NOT_FOUND)
end end
@ -175,12 +171,12 @@ shared_examples 'basic GRPC message delivery is OK' do
call = new_client_call call = new_client_call
client_sends(call) client_sends(call)
server_call = server_receives_and_responds_with('server_response') server_call = server_receives_and_responds_with('server_response')
server_call.start_write_status(10101, 'status code is 10101', @server_tag) server_call.start_write_status(10_101, 'status code is 10101', @server_tag)
# first the client says writes are done # first the client says writes are done
call.start_read(@tag) call.start_read(@tag)
ev = expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag) expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag)
ev = expect_next_event_on(@client_queue, READ, @tag) expect_next_event_on(@client_queue, READ, @tag)
call.writes_done(@tag) call.writes_done(@tag)
# but nothing happens until the server sends a status # but nothing happens until the server sends a status
@ -192,24 +188,23 @@ shared_examples 'basic GRPC message delivery is OK' do
expect_next_event_on(@client_queue, FINISH_ACCEPTED, @tag) expect_next_event_on(@client_queue, FINISH_ACCEPTED, @tag)
ev = expect_next_event_on(@client_queue, FINISHED, @client_finished_tag) ev = expect_next_event_on(@client_queue, FINISHED, @client_finished_tag)
expect(ev.result.details).to eq('status code is 10101') expect(ev.result.details).to eq('status code is 10101')
expect(ev.result.code).to eq(10101) expect(ev.result.code).to eq(10_101)
end end
end end
shared_examples 'GRPC metadata delivery works OK' do shared_examples 'GRPC metadata delivery works OK' do
include_context 'setup: tags' include_context 'setup: tags'
describe 'from client => server' do describe 'from client => server' do
before(:example) do before(:example) do
n = 7 # arbitrary number of metadata n = 7 # arbitrary number of metadata
diff_keys = Hash[n.times.collect { |i| ['k%d' % i, 'v%d' % i] }] diff_keys_fn = proc { |i| [sprintf('k%d', i), sprintf('v%d', i)] }
null_vals = Hash[n.times.collect { |i| ['k%d' % i, 'v\0%d' % i] }] diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
same_keys = Hash[n.times.collect { |i| ['k%d' % i, ['v%d' % i] * n] }] null_vals_fn = proc { |i| [sprintf('k%d', i), sprintf('v\0%d', i)] }
symbol_key = {:a_key => 'a val'} null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
same_keys_fn = proc { |i| [sprintf('k%d', i), [sprintf('v%d', i)] * n] }
same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
symbol_key = { a_key: 'a val' }
@valid_metadata = [diff_keys, same_keys, null_vals, symbol_key] @valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
@bad_keys = [] @bad_keys = []
@bad_keys << { Object.new => 'a value' } @bad_keys << { Object.new => 'a value' }
@ -239,7 +234,7 @@ shared_examples 'GRPC metadata delivery works OK' do
# Client begins a call OK # Client begins a call OK
call.start_invoke(@client_queue, @tag, @tag, @client_finished_tag) call.start_invoke(@client_queue, @tag, @tag, @client_finished_tag)
ev = expect_next_event_on(@client_queue, INVOKE_ACCEPTED, @tag) expect_next_event_on(@client_queue, INVOKE_ACCEPTED, @tag)
# ... server has all metadata available even though the client did not # ... server has all metadata available even though the client did not
# send a write # send a write
@ -250,17 +245,18 @@ shared_examples 'GRPC metadata delivery works OK' do
expect(result.merge(replace_symbols)).to eq(result) expect(result.merge(replace_symbols)).to eq(result)
end end
end end
end end
describe 'from server => client' do describe 'from server => client' do
before(:example) do before(:example) do
n = 7 # arbitrary number of metadata n = 7 # arbitrary number of metadata
diff_keys = Hash[n.times.collect { |i| ['k%d' % i, 'v%d' % i] }] diff_keys_fn = proc { |i| [sprintf('k%d', i), sprintf('v%d', i)] }
null_vals = Hash[n.times.collect { |i| ['k%d' % i, 'v\0%d' % i] }] diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
same_keys = Hash[n.times.collect { |i| ['k%d' % i, ['v%d' % i] * n] }] null_vals_fn = proc { |i| [sprintf('k%d', i), sprintf('v\0%d', i)] }
symbol_key = {:a_key => 'a val'} null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
same_keys_fn = proc { |i| [sprintf('k%d', i), [sprintf('v%d', i)] * n] }
same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
symbol_key = { a_key: 'a val' }
@valid_metadata = [diff_keys, same_keys, null_vals, symbol_key] @valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
@bad_keys = [] @bad_keys = []
@bad_keys << { Object.new => 'a value' } @bad_keys << { Object.new => 'a value' }
@ -290,7 +286,7 @@ shared_examples 'GRPC metadata delivery works OK' do
# ... server accepts the call without adding metadata # ... server accepts the call without adding metadata
server_call.server_accept(@server_queue, @server_finished_tag) server_call.server_accept(@server_queue, @server_finished_tag)
server_call.server_end_initial_metadata() server_call.server_end_initial_metadata
# ... these server sends some data, allowing the metadata read # ... these server sends some data, allowing the metadata read
server_call.start_write(ByteBuffer.new('reply with metadata'), server_call.start_write(ByteBuffer.new('reply with metadata'),
@ -300,7 +296,7 @@ shared_examples 'GRPC metadata delivery works OK' do
# there is the HTTP status metadata, though there should not be any # there is the HTTP status metadata, though there should not be any
# TODO(temiola): update this with the bug number to be resolved # TODO(temiola): update this with the bug number to be resolved
ev = expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag) ev = expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag)
expect(ev.result).to eq({':status' => '200'}) expect(ev.result).to eq(':status' => '200')
end end
it 'sends all the pairs and status:200 when keys and values are valid' do it 'sends all the pairs and status:200 when keys and values are valid' do
@ -316,7 +312,7 @@ shared_examples 'GRPC metadata delivery works OK' do
# ... server adds metadata and accepts the call # ... server adds metadata and accepts the call
server_call.add_metadata(md) server_call.add_metadata(md)
server_call.server_accept(@server_queue, @server_finished_tag) server_call.server_accept(@server_queue, @server_finished_tag)
server_call.server_end_initial_metadata() server_call.server_end_initial_metadata
# Now the client can read the metadata # Now the client can read the metadata
ev = expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag) ev = expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag)
@ -324,16 +320,11 @@ shared_examples 'GRPC metadata delivery works OK' do
replace_symbols[':status'] = '200' replace_symbols[':status'] = '200'
expect(ev.result).to eq(replace_symbols) expect(ev.result).to eq(replace_symbols)
end end
end end
end end
end end
describe 'the http client/server' do describe 'the http client/server' do
before(:example) do before(:example) do
port = find_unused_tcp_port port = find_unused_tcp_port
host = "localhost:#{port}" host = "localhost:#{port}"
@ -354,11 +345,9 @@ describe 'the http client/server' do
it_behaves_like 'GRPC metadata delivery works OK' do it_behaves_like 'GRPC metadata delivery works OK' do
end end
end end
describe 'the secure http client/server' do describe 'the secure http client/server' do
before(:example) do before(:example) do
certs = load_test_certs certs = load_test_certs
port = find_unused_tcp_port port = find_unused_tcp_port
@ -383,5 +372,4 @@ describe 'the secure http client/server' do
it_behaves_like 'GRPC metadata delivery works OK' do it_behaves_like 'GRPC metadata delivery works OK' do
end end
end end

@ -30,7 +30,6 @@
require 'grpc' require 'grpc'
describe GRPC::Core::CompletionQueue do describe GRPC::Core::CompletionQueue do
describe '#new' do describe '#new' do
it 'is constructed successufully' do it 'is constructed successufully' do
expect { GRPC::Core::CompletionQueue.new }.not_to raise_error expect { GRPC::Core::CompletionQueue.new }.not_to raise_error
@ -53,7 +52,6 @@ describe GRPC::Core::CompletionQueue do
expect { ch.next(a_time) }.not_to raise_error expect { ch.next(a_time) }.not_to raise_error
end end
end end
end end
describe '#pluck' do describe '#pluck' do
@ -74,8 +72,5 @@ describe GRPC::Core::CompletionQueue do
expect { ch.pluck(tag, a_time) }.not_to raise_error expect { ch.pluck(tag, a_time) }.not_to raise_error
end end
end end
end end
end end

@ -29,7 +29,6 @@
require 'grpc' require 'grpc'
def load_test_certs def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata') test_root = File.join(File.dirname(__FILE__), 'testdata')
files = ['ca.pem', 'server1.pem', 'server1.key'] files = ['ca.pem', 'server1.pem', 'server1.key']
@ -39,9 +38,7 @@ end
Credentials = GRPC::Core::Credentials Credentials = GRPC::Core::Credentials
describe Credentials do describe Credentials do
describe '#new' do describe '#new' do
it 'can be constructed with fake inputs' do it 'can be constructed with fake inputs' do
expect { Credentials.new('root_certs', 'key', 'cert') }.not_to raise_error expect { Credentials.new('root_certs', 'key', 'cert') }.not_to raise_error
end end
@ -58,30 +55,23 @@ describe Credentials do
it 'cannot be constructed with a nil server roots' do it 'cannot be constructed with a nil server roots' do
_, client_key, client_chain = load_test_certs _, client_key, client_chain = load_test_certs
blk = Proc.new { Credentials.new(nil, client_key, client_chain) } blk = proc { Credentials.new(nil, client_key, client_chain) }
expect(&blk).to raise_error expect(&blk).to raise_error
end end
end end
describe '#compose' do describe '#compose' do
it 'can be completed OK' do it 'can be completed OK' do
certs = load_test_certs certs = load_test_certs
cred1 = Credentials.new(*certs) cred1 = Credentials.new(*certs)
cred2 = Credentials.new(*certs) cred2 = Credentials.new(*certs)
expect { cred1.compose(cred2) }.to_not raise_error expect { cred1.compose(cred2) }.to_not raise_error
end end
end end
describe 'Credentials#default' do describe 'Credentials#default' do
it 'is not implemented yet' do it 'is not implemented yet' do
expect { Credentials.default() }.to raise_error RuntimeError expect { Credentials.default }.to raise_error RuntimeError
end end
end end
end end

@ -30,25 +30,23 @@
require 'grpc' require 'grpc'
describe GRPC::Core::CompletionType do describe GRPC::Core::CompletionType do
before(:each) do before(:each) do
@known_types = { @known_types = {
:QUEUE_SHUTDOWN => 0, QUEUE_SHUTDOWN: 0,
:READ => 1, READ: 1,
:INVOKE_ACCEPTED => 2, INVOKE_ACCEPTED: 2,
:WRITE_ACCEPTED => 3, WRITE_ACCEPTED: 3,
:FINISH_ACCEPTED => 4, FINISH_ACCEPTED: 4,
:CLIENT_METADATA_READ => 5, CLIENT_METADATA_READ: 5,
:FINISHED => 6, FINISHED: 6,
:SERVER_RPC_NEW => 7, SERVER_RPC_NEW: 7,
:RESERVED => 8 RESERVED: 8
} }
end end
it 'should have all the known types' do it 'should have all the known types' do
mod = GRPC::Core::CompletionType mod = GRPC::Core::CompletionType
blk = Proc.new { Hash[mod.constants.collect { |c| [c, mod.const_get(c)] }] } blk = proc { Hash[mod.constants.collect { |c| [c, mod.const_get(c)] }] }
expect(blk.call).to eq(@known_types) expect(blk.call).to eq(@known_types)
end end
end end

@ -38,9 +38,9 @@ describe GRPC::ActiveCall do
CompletionType = GRPC::Core::CompletionType CompletionType = GRPC::Core::CompletionType
before(:each) do before(:each) do
@pass_through = Proc.new { |x| x } @pass_through = proc { |x| x }
@server_tag = Object.new @server_tag = Object.new
@server_done_tag, meta_tag = Object.new @server_done_tag = Object.new
@tag = Object.new @tag = Object.new
@client_queue = GRPC::Core::CompletionQueue.new @client_queue = GRPC::Core::CompletionQueue.new
@ -70,7 +70,7 @@ describe GRPC::ActiveCall do
describe '#multi_req_view' do describe '#multi_req_view' do
it 'exposes a fixed subset of the ActiveCall methods' do it 'exposes a fixed subset of the ActiveCall methods' do
want = ['cancelled', 'deadline', 'each_remote_read', 'shutdown'] want = %w(cancelled, deadline, each_remote_read, shutdown)
v = @client_call.multi_req_view v = @client_call.multi_req_view
want.each do |w| want.each do |w|
expect(v.methods.include?(w)) expect(v.methods.include?(w))
@ -80,7 +80,7 @@ describe GRPC::ActiveCall do
describe '#single_req_view' do describe '#single_req_view' do
it 'exposes a fixed subset of the ActiveCall methods' do it 'exposes a fixed subset of the ActiveCall methods' do
want = ['cancelled', 'deadline', 'shutdown'] want = %w(cancelled, deadline, shutdown)
v = @client_call.single_req_view v = @client_call.single_req_view
want.each do |w| want.each do |w|
expect(v.methods.include?(w)) expect(v.methods.include?(w))
@ -110,7 +110,7 @@ describe GRPC::ActiveCall do
# Accept the call, and verify that the server reads the response ok. # Accept the call, and verify that the server reads the response ok.
ev.call.server_accept(@client_queue, @server_tag) ev.call.server_accept(@client_queue, @server_tag)
ev.call.server_end_initial_metadata() ev.call.server_end_initial_metadata
server_call = ActiveCall.new(ev.call, @client_queue, @pass_through, server_call = ActiveCall.new(ev.call, @client_queue, @pass_through,
@pass_through, deadline) @pass_through, deadline)
expect(server_call.remote_read).to eq(msg) expect(server_call.remote_read).to eq(msg)
@ -120,7 +120,7 @@ describe GRPC::ActiveCall do
call = make_test_call call = make_test_call
done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue, done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue,
deadline) deadline)
marshal = Proc.new { |x| 'marshalled:' + x } marshal = proc { |x| 'marshalled:' + x }
client_call = ActiveCall.new(call, @client_queue, marshal, client_call = ActiveCall.new(call, @client_queue, marshal,
@pass_through, deadline, @pass_through, deadline,
finished_tag: done_tag, finished_tag: done_tag,
@ -132,33 +132,29 @@ describe GRPC::ActiveCall do
@server.request_call(@server_tag) @server.request_call(@server_tag)
ev = @server_queue.next(deadline) ev = @server_queue.next(deadline)
ev.call.server_accept(@client_queue, @server_tag) ev.call.server_accept(@client_queue, @server_tag)
ev.call.server_end_initial_metadata() ev.call.server_end_initial_metadata
server_call = ActiveCall.new(ev.call, @client_queue, @pass_through, server_call = ActiveCall.new(ev.call, @client_queue, @pass_through,
@pass_through, deadline) @pass_through, deadline)
expect(server_call.remote_read).to eq('marshalled:' + msg) expect(server_call.remote_read).to eq('marshalled:' + msg)
end end
end end
describe '#client_start_invoke' do describe '#client_start_invoke' do
it 'sends keywords as metadata to the server when the are present' do it 'sends keywords as metadata to the server when the are present' do
call, pass_through = make_test_call, Proc.new { |x| x } call = make_test_call
done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue, ActiveCall.client_start_invoke(call, @client_queue, deadline,
deadline, k1: 'v1', k1: 'v1', k2: 'v2')
k2: 'v2')
@server.request_call(@server_tag) @server.request_call(@server_tag)
ev = @server_queue.next(deadline) ev = @server_queue.next(deadline)
expect(ev).to_not be_nil expect(ev).to_not be_nil
expect(ev.result.metadata['k1']).to eq('v1') expect(ev.result.metadata['k1']).to eq('v1')
expect(ev.result.metadata['k2']).to eq('v2') expect(ev.result.metadata['k2']).to eq('v2')
end end
end end
describe '#remote_read' do describe '#remote_read' do
it 'reads the response sent by a server' do it 'reads the response sent by a server' do
call, pass_through = make_test_call, Proc.new { |x| x } call = make_test_call
done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue, done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue,
deadline) deadline)
client_call = ActiveCall.new(call, @client_queue, @pass_through, client_call = ActiveCall.new(call, @client_queue, @pass_through,
@ -173,7 +169,7 @@ describe GRPC::ActiveCall do
end end
it 'saves metadata { status=200 } when the server adds no metadata' do it 'saves metadata { status=200 } when the server adds no metadata' do
call, pass_through = make_test_call, Proc.new { |x| x } call = make_test_call
done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue, done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue,
deadline) deadline)
client_call = ActiveCall.new(call, @client_queue, @pass_through, client_call = ActiveCall.new(call, @client_queue, @pass_through,
@ -186,11 +182,11 @@ describe GRPC::ActiveCall do
server_call.remote_send('ignore me') server_call.remote_send('ignore me')
expect(client_call.metadata).to be_nil expect(client_call.metadata).to be_nil
client_call.remote_read client_call.remote_read
expect(client_call.metadata).to eq({':status' => '200'}) expect(client_call.metadata).to eq(':status' => '200')
end end
it 'saves metadata add by the server' do it 'saves metadata add by the server' do
call, pass_through = make_test_call, Proc.new { |x| x } call = make_test_call
done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue, done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue,
deadline) deadline)
client_call = ActiveCall.new(call, @client_queue, @pass_through, client_call = ActiveCall.new(call, @client_queue, @pass_through,
@ -203,13 +199,12 @@ describe GRPC::ActiveCall do
server_call.remote_send('ignore me') server_call.remote_send('ignore me')
expect(client_call.metadata).to be_nil expect(client_call.metadata).to be_nil
client_call.remote_read client_call.remote_read
expect(client_call.metadata).to eq({':status' => '200', 'k1' => 'v1', expected = { ':status' => '200', 'k1' => 'v1', 'k2' => 'v2' }
'k2' => 'v2'}) expect(client_call.metadata).to eq(expected)
end end
it 'get a nil msg before a status when an OK status is sent' do it 'get a nil msg before a status when an OK status is sent' do
call, pass_through = make_test_call, Proc.new { |x| x } call = make_test_call
done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue, done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue,
deadline) deadline)
client_call = ActiveCall.new(call, @client_queue, @pass_through, client_call = ActiveCall.new(call, @client_queue, @pass_through,
@ -227,12 +222,11 @@ describe GRPC::ActiveCall do
expect(res).to be_nil expect(res).to be_nil
end end
it 'unmarshals the response using the unmarshal func' do it 'unmarshals the response using the unmarshal func' do
call = make_test_call call = make_test_call
done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue, done_tag, meta_tag = ActiveCall.client_start_invoke(call, @client_queue,
deadline) deadline)
unmarshal = Proc.new { |x| 'unmarshalled:' + x } unmarshal = proc { |x| 'unmarshalled:' + x }
client_call = ActiveCall.new(call, @client_queue, @pass_through, client_call = ActiveCall.new(call, @client_queue, @pass_through,
unmarshal, deadline, unmarshal, deadline,
finished_tag: done_tag, finished_tag: done_tag,
@ -245,7 +239,6 @@ describe GRPC::ActiveCall do
server_call.remote_send('server_response') server_call.remote_send('server_response')
expect(client_call.remote_read).to eq('unmarshalled:server_response') expect(client_call.remote_read).to eq('unmarshalled:server_response')
end end
end end
describe '#each_remote_read' do describe '#each_remote_read' do
@ -298,7 +291,6 @@ describe GRPC::ActiveCall do
server_call.send_status(OK, 'OK') server_call.send_status(OK, 'OK')
expect { e.next }.to raise_error(StopIteration) expect { e.next }.to raise_error(StopIteration)
end end
end end
describe '#writes_done' do describe '#writes_done' do
@ -357,7 +349,6 @@ describe GRPC::ActiveCall do
expect { client_call.writes_done(true) }.to_not raise_error expect { client_call.writes_done(true) }.to_not raise_error
expect { server_call.finished }.to_not raise_error expect { server_call.finished }.to_not raise_error
end end
end end
def expect_server_to_receive(sent_text, **kw) def expect_server_to_receive(sent_text, **kw)
@ -371,7 +362,7 @@ describe GRPC::ActiveCall do
ev = @server_queue.next(deadline) ev = @server_queue.next(deadline)
ev.call.add_metadata(kw) ev.call.add_metadata(kw)
ev.call.server_accept(@client_queue, @server_done_tag) ev.call.server_accept(@client_queue, @server_done_tag)
ev.call.server_end_initial_metadata() ev.call.server_end_initial_metadata
ActiveCall.new(ev.call, @client_queue, @pass_through, ActiveCall.new(ev.call, @client_queue, @pass_through,
@pass_through, deadline, @pass_through, deadline,
finished_tag: @server_done_tag) finished_tag: @server_done_tag)
@ -384,5 +375,4 @@ describe GRPC::ActiveCall do
def deadline def deadline
Time.now + 0.25 # in 0.25 seconds; arbitrary Time.now + 0.25 # in 0.25 seconds; arbitrary
end end
end end

@ -31,7 +31,7 @@ require 'grpc'
require 'xray/thread_dump_signal_handler' require 'xray/thread_dump_signal_handler'
require_relative '../port_picker' require_relative '../port_picker'
NOOP = Proc.new { |x| x } NOOP = proc { |x| x }
def wakey_thread(&blk) def wakey_thread(&blk)
awake_mutex, awake_cond = Mutex.new, ConditionVariable.new awake_mutex, awake_cond = Mutex.new, ConditionVariable.new
@ -52,7 +52,6 @@ include GRPC::Core::StatusCodes
include GRPC::Core::TimeConsts include GRPC::Core::TimeConsts
describe 'ClientStub' do describe 'ClientStub' do
before(:each) do before(:each) do
Thread.abort_on_exception = true Thread.abort_on_exception = true
@server = nil @server = nil
@ -67,11 +66,10 @@ describe 'ClientStub' do
end end
describe '#new' do describe '#new' do
it 'can be created from a host and args' do it 'can be created from a host and args' do
host = new_test_host host = new_test_host
opts = {:a_channel_arg => 'an_arg'} opts = { a_channel_arg: 'an_arg' }
blk = Proc.new do blk = proc do
GRPC::ClientStub.new(host, @cq, **opts) GRPC::ClientStub.new(host, @cq, **opts)
end end
expect(&blk).not_to raise_error expect(&blk).not_to raise_error
@ -79,8 +77,8 @@ describe 'ClientStub' do
it 'can be created with a default deadline' do it 'can be created with a default deadline' do
host = new_test_host host = new_test_host
opts = {:a_channel_arg => 'an_arg', :deadline => 5} opts = { a_channel_arg: 'an_arg', deadline: 5 }
blk = Proc.new do blk = proc do
GRPC::ClientStub.new(host, @cq, **opts) GRPC::ClientStub.new(host, @cq, **opts)
end end
expect(&blk).not_to raise_error expect(&blk).not_to raise_error
@ -88,8 +86,8 @@ describe 'ClientStub' do
it 'can be created with an channel override' do it 'can be created with an channel override' do
host = new_test_host host = new_test_host
opts = {:a_channel_arg => 'an_arg', :channel_override => @ch} opts = { a_channel_arg: 'an_arg', channel_override: @ch }
blk = Proc.new do blk = proc do
GRPC::ClientStub.new(host, @cq, **opts) GRPC::ClientStub.new(host, @cq, **opts)
end end
expect(&blk).not_to raise_error expect(&blk).not_to raise_error
@ -97,8 +95,8 @@ describe 'ClientStub' do
it 'cannot be created with a bad channel override' do it 'cannot be created with a bad channel override' do
host = new_test_host host = new_test_host
blk = Proc.new do blk = proc do
opts = {:a_channel_arg => 'an_arg', :channel_override => Object.new} opts = { a_channel_arg: 'an_arg', channel_override: Object.new }
GRPC::ClientStub.new(host, @cq, **opts) GRPC::ClientStub.new(host, @cq, **opts)
end end
expect(&blk).to raise_error expect(&blk).to raise_error
@ -106,8 +104,8 @@ describe 'ClientStub' do
it 'cannot be created with bad credentials' do it 'cannot be created with bad credentials' do
host = new_test_host host = new_test_host
blk = Proc.new do blk = proc do
opts = {:a_channel_arg => 'an_arg', :creds => Object.new} opts = { a_channel_arg: 'an_arg', creds: Object.new }
GRPC::ClientStub.new(host, @cq, **opts) GRPC::ClientStub.new(host, @cq, **opts)
end end
expect(&blk).to raise_error expect(&blk).to raise_error
@ -116,17 +114,16 @@ describe 'ClientStub' do
it 'can be created with test test credentials' do it 'can be created with test test credentials' do
certs = load_test_certs certs = load_test_certs
host = new_test_host host = new_test_host
blk = Proc.new do blk = proc do
opts = { opts = {
GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com', GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com',
:a_channel_arg => 'an_arg', a_channel_arg: 'an_arg',
:creds => GRPC::Core::Credentials.new(certs[0], nil, nil) creds: GRPC::Core::Credentials.new(certs[0], nil, nil)
} }
GRPC::ClientStub.new(host, @cq, **opts) GRPC::ClientStub.new(host, @cq, **opts)
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
end end
describe '#request_response' do describe '#request_response' do
@ -135,7 +132,6 @@ describe 'ClientStub' do
end end
shared_examples 'request response' do shared_examples 'request response' do
it 'should send a request to/receive a reply from a server' do it 'should send a request to/receive a reply from a server' do
host = new_test_host host = new_test_host
th = run_request_response(host, @sent_msg, @resp, @pass) th = run_request_response(host, @sent_msg, @resp, @pass)
@ -146,8 +142,8 @@ describe 'ClientStub' do
it 'should send metadata to the server ok' do it 'should send metadata to the server ok' do
host = new_test_host host = new_test_host
th = run_request_response(host, @sent_msg, @resp, @pass, k1: 'v1', th = run_request_response(host, @sent_msg, @resp, @pass,
k2: 'v2') k1: 'v1', k2: 'v2')
stub = GRPC::ClientStub.new(host, @cq) stub = GRPC::ClientStub.new(host, @cq)
expect(get_response(stub)).to eq(@resp) expect(get_response(stub)).to eq(@resp)
th.join th.join
@ -157,7 +153,10 @@ describe 'ClientStub' do
host = new_test_host host = new_test_host
th = run_request_response(host, @sent_msg, @resp, @pass, th = run_request_response(host, @sent_msg, @resp, @pass,
k1: 'updated-v1', k2: 'v2') k1: 'updated-v1', k2: 'v2')
update_md = Proc.new { |md| md[:k1] = 'updated-v1'; md } update_md = proc do |md|
md[:k1] = 'updated-v1'
md
end
stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md) stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md)
expect(get_response(stub)).to eq(@resp) expect(get_response(stub)).to eq(@resp)
th.join th.join
@ -176,43 +175,35 @@ describe 'ClientStub' do
host = new_test_host host = new_test_host
th = run_request_response(host, @sent_msg, @resp, @fail) th = run_request_response(host, @sent_msg, @resp, @fail)
stub = GRPC::ClientStub.new(host, @cq) stub = GRPC::ClientStub.new(host, @cq)
blk = Proc.new { get_response(stub) } blk = proc { get_response(stub) }
expect(&blk).to raise_error(GRPC::BadStatus) expect(&blk).to raise_error(GRPC::BadStatus)
th.join th.join
end end
end end
describe 'without a call operation' do describe 'without a call operation' do
def get_response(stub) def get_response(stub)
stub.request_response(@method, @sent_msg, NOOP, NOOP, k1: 'v1', stub.request_response(@method, @sent_msg, NOOP, NOOP,
k2: 'v2') k1: 'v1', k2: 'v2')
end end
it_behaves_like 'request response' it_behaves_like 'request response'
end end
describe 'via a call operation' do describe 'via a call operation' do
def get_response(stub) def get_response(stub)
op = stub.request_response(@method, @sent_msg, NOOP, NOOP, op = stub.request_response(@method, @sent_msg, NOOP, NOOP,
return_op: true, k1: 'v1', k2: 'v2') return_op: true, k1: 'v1', k2: 'v2')
expect(op).to be_a(GRPC::ActiveCall::Operation) expect(op).to be_a(GRPC::ActiveCall::Operation)
op.execute() op.execute
end end
it_behaves_like 'request response' it_behaves_like 'request response'
end end
end end
describe '#client_streamer' do describe '#client_streamer' do
shared_examples 'client streaming' do shared_examples 'client streaming' do
before(:each) do before(:each) do
@sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s } @sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
@resp = 'a_reply' @resp = 'a_reply'
@ -228,19 +219,21 @@ describe 'ClientStub' do
it 'should send metadata to the server ok' do it 'should send metadata to the server ok' do
host = new_test_host host = new_test_host
th = run_client_streamer(host, @sent_msgs, @resp, @pass, k1: 'v1', th = run_client_streamer(host, @sent_msgs, @resp, @pass,
k2: 'v2') k1: 'v1', k2: 'v2')
stub = GRPC::ClientStub.new(host, @cq) stub = GRPC::ClientStub.new(host, @cq)
expect(get_response(stub)).to eq(@resp) expect(get_response(stub)).to eq(@resp)
th.join th.join
end end
it 'should update the sent metadata with a provided metadata updater' do it 'should update the sent metadata with a provided metadata updater' do
host = new_test_host host = new_test_host
th = run_client_streamer(host, @sent_msgs, @resp, @pass, th = run_client_streamer(host, @sent_msgs, @resp, @pass,
k1: 'updated-v1', k2: 'v2') k1: 'updated-v1', k2: 'v2')
update_md = Proc.new { |md| md[:k1] = 'updated-v1'; md } update_md = proc do |md|
md[:k1] = 'updated-v1'
md
end
stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md) stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md)
expect(get_response(stub)).to eq(@resp) expect(get_response(stub)).to eq(@resp)
th.join th.join
@ -250,43 +243,35 @@ describe 'ClientStub' do
host = new_test_host host = new_test_host
th = run_client_streamer(host, @sent_msgs, @resp, @fail) th = run_client_streamer(host, @sent_msgs, @resp, @fail)
stub = GRPC::ClientStub.new(host, @cq) stub = GRPC::ClientStub.new(host, @cq)
blk = Proc.new { get_response(stub) } blk = proc { get_response(stub) }
expect(&blk).to raise_error(GRPC::BadStatus) expect(&blk).to raise_error(GRPC::BadStatus)
th.join th.join
end end
end end
describe 'without a call operation' do describe 'without a call operation' do
def get_response(stub) def get_response(stub)
stub.client_streamer(@method, @sent_msgs, NOOP, NOOP, k1: 'v1', stub.client_streamer(@method, @sent_msgs, NOOP, NOOP,
k2: 'v2') k1: 'v1', k2: 'v2')
end end
it_behaves_like 'client streaming' it_behaves_like 'client streaming'
end end
describe 'via a call operation' do describe 'via a call operation' do
def get_response(stub) def get_response(stub)
op = stub.client_streamer(@method, @sent_msgs, NOOP, NOOP, op = stub.client_streamer(@method, @sent_msgs, NOOP, NOOP,
return_op: true, k1: 'v1', k2: 'v2') return_op: true, k1: 'v1', k2: 'v2')
expect(op).to be_a(GRPC::ActiveCall::Operation) expect(op).to be_a(GRPC::ActiveCall::Operation)
resp = op.execute() op.execute
end end
it_behaves_like 'client streaming' it_behaves_like 'client streaming'
end end
end end
describe '#server_streamer' do describe '#server_streamer' do
shared_examples 'server streaming' do shared_examples 'server streaming' do
before(:each) do before(:each) do
@sent_msg = 'a_msg' @sent_msg = 'a_msg'
@replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s } @replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
@ -311,8 +296,8 @@ describe 'ClientStub' do
it 'should send metadata to the server ok' do it 'should send metadata to the server ok' do
host = new_test_host host = new_test_host
th = run_server_streamer(host, @sent_msg, @replys, @fail, k1: 'v1', th = run_server_streamer(host, @sent_msg, @replys, @fail,
k2: 'v2') k1: 'v1', k2: 'v2')
stub = GRPC::ClientStub.new(host, @cq) stub = GRPC::ClientStub.new(host, @cq)
e = get_responses(stub) e = get_responses(stub)
expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus) expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus)
@ -323,55 +308,50 @@ describe 'ClientStub' do
host = new_test_host host = new_test_host
th = run_server_streamer(host, @sent_msg, @replys, @pass, th = run_server_streamer(host, @sent_msg, @replys, @pass,
k1: 'updated-v1', k2: 'v2') k1: 'updated-v1', k2: 'v2')
update_md = Proc.new { |md| md[:k1] = 'updated-v1'; md } update_md = proc do |md|
md[:k1] = 'updated-v1'
md
end
stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md) stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md)
e = get_responses(stub) e = get_responses(stub)
expect(e.collect { |r| r }).to eq(@replys) expect(e.collect { |r| r }).to eq(@replys)
th.join th.join
end end
end end
describe 'without a call operation' do describe 'without a call operation' do
def get_responses(stub) def get_responses(stub)
e = stub.server_streamer(@method, @sent_msg, NOOP, NOOP, k1: 'v1', e = stub.server_streamer(@method, @sent_msg, NOOP, NOOP,
k2: 'v2') k1: 'v1', k2: 'v2')
expect(e).to be_a(Enumerator) expect(e).to be_a(Enumerator)
e e
end end
it_behaves_like 'server streaming' it_behaves_like 'server streaming'
end end
describe 'via a call operation' do describe 'via a call operation' do
def get_responses(stub) def get_responses(stub)
op = stub.server_streamer(@method, @sent_msg, NOOP, NOOP, op = stub.server_streamer(@method, @sent_msg, NOOP, NOOP,
return_op: true, k1: 'v1', k2: 'v2') return_op: true, k1: 'v1', k2: 'v2')
expect(op).to be_a(GRPC::ActiveCall::Operation) expect(op).to be_a(GRPC::ActiveCall::Operation)
e = op.execute() e = op.execute
expect(e).to be_a(Enumerator) expect(e).to be_a(Enumerator)
e e
end end
it_behaves_like 'server streaming' it_behaves_like 'server streaming'
end end
end end
describe '#bidi_streamer' do describe '#bidi_streamer' do
shared_examples 'bidi streaming' do shared_examples 'bidi streaming' do
before(:each) do before(:each) do
@sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s } @sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
@replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s } @replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
end end
it 'supports sending all the requests first', :bidi => true do it 'supports sending all the requests first', bidi: true do
host = new_test_host host = new_test_host
th = run_bidi_streamer_handle_inputs_first(host, @sent_msgs, @replys, th = run_bidi_streamer_handle_inputs_first(host, @sent_msgs, @replys,
@pass) @pass)
@ -381,7 +361,7 @@ describe 'ClientStub' do
th.join th.join
end end
it 'supports client-initiated ping pong', :bidi => true do it 'supports client-initiated ping pong', bidi: true do
host = new_test_host host = new_test_host
th = run_bidi_streamer_echo_ping_pong(host, @sent_msgs, @pass, true) th = run_bidi_streamer_echo_ping_pong(host, @sent_msgs, @pass, true)
stub = GRPC::ClientStub.new(host, @cq) stub = GRPC::ClientStub.new(host, @cq)
@ -396,7 +376,7 @@ describe 'ClientStub' do
# servers don't know if all the client metadata has been sent until # servers don't know if all the client metadata has been sent until
# they receive a message from the client. Without receiving all the # they receive a message from the client. Without receiving all the
# metadata, the server does not accept the call, so this test hangs. # metadata, the server does not accept the call, so this test hangs.
xit 'supports a server-initiated ping pong', :bidi => true do xit 'supports a server-initiated ping pong', bidi: true do
host = new_test_host host = new_test_host
th = run_bidi_streamer_echo_ping_pong(host, @sent_msgs, @pass, false) th = run_bidi_streamer_echo_ping_pong(host, @sent_msgs, @pass, false)
stub = GRPC::ClientStub.new(host, @cq) stub = GRPC::ClientStub.new(host, @cq)
@ -404,11 +384,9 @@ describe 'ClientStub' do
expect(e.collect { |r| r }).to eq(@sent_msgs) expect(e.collect { |r| r }).to eq(@sent_msgs)
th.join th.join
end end
end end
describe 'without a call operation' do describe 'without a call operation' do
def get_responses(stub) def get_responses(stub)
e = stub.bidi_streamer(@method, @sent_msgs, NOOP, NOOP) e = stub.bidi_streamer(@method, @sent_msgs, NOOP, NOOP)
expect(e).to be_a(Enumerator) expect(e).to be_a(Enumerator)
@ -416,13 +394,12 @@ describe 'ClientStub' do
end end
it_behaves_like 'bidi streaming' it_behaves_like 'bidi streaming'
end end
describe 'via a call operation' do describe 'via a call operation' do
def get_responses(stub) def get_responses(stub)
op = stub.bidi_streamer(@method, @sent_msgs, NOOP, NOOP, return_op:true) op = stub.bidi_streamer(@method, @sent_msgs, NOOP, NOOP,
return_op: true)
expect(op).to be_a(GRPC::ActiveCall::Operation) expect(op).to be_a(GRPC::ActiveCall::Operation)
e = op.execute e = op.execute
expect(e).to be_a(Enumerator) expect(e).to be_a(Enumerator)
@ -430,9 +407,7 @@ describe 'ClientStub' do
end end
it_behaves_like 'bidi streaming' it_behaves_like 'bidi streaming'
end end
end end
def run_server_streamer(hostname, expected_input, replys, status, **kw) def run_server_streamer(hostname, expected_input, replys, status, **kw)
@ -514,14 +489,13 @@ describe 'ClientStub' do
def expect_server_to_be_invoked(hostname, awake_mutex, awake_cond) def expect_server_to_be_invoked(hostname, awake_mutex, awake_cond)
server_queue = start_test_server(hostname, awake_mutex, awake_cond) server_queue = start_test_server(hostname, awake_mutex, awake_cond)
test_deadline = Time.now + 10 # fail tests after 10 seconds
ev = server_queue.pluck(@server_tag, INFINITE_FUTURE) ev = server_queue.pluck(@server_tag, INFINITE_FUTURE)
raise OutOfTime if ev.nil? fail OutOfTime if ev.nil?
server_call = ev.call server_call = ev.call
server_call.metadata = ev.result.metadata server_call.metadata = ev.result.metadata
finished_tag = Object.new finished_tag = Object.new
server_call.server_accept(server_queue, finished_tag) server_call.server_accept(server_queue, finished_tag)
server_call.server_end_initial_metadata() server_call.server_end_initial_metadata
GRPC::ActiveCall.new(server_call, server_queue, NOOP, NOOP, INFINITE_FUTURE, GRPC::ActiveCall.new(server_call, server_queue, NOOP, NOOP, INFINITE_FUTURE,
finished_tag: finished_tag) finished_tag: finished_tag)
end end
@ -530,5 +504,4 @@ describe 'ClientStub' do
port = find_unused_tcp_port port = find_unused_tcp_port
"localhost:#{port}" "localhost:#{port}"
end end
end end

@ -30,9 +30,7 @@
require 'grpc' require 'grpc'
require 'grpc/generic/rpc_desc' require 'grpc/generic/rpc_desc'
describe GRPC::RpcDesc do describe GRPC::RpcDesc do
RpcDesc = GRPC::RpcDesc RpcDesc = GRPC::RpcDesc
Stream = RpcDesc::Stream Stream = RpcDesc::Stream
OK = GRPC::Core::StatusCodes::OK OK = GRPC::Core::StatusCodes::OK
@ -56,7 +54,6 @@ describe GRPC::RpcDesc do
end end
describe '#run_server_method' do describe '#run_server_method' do
describe 'for request responses' do describe 'for request responses' do
before(:each) do before(:each) do
@call = double('active_call') @call = double('active_call')
@ -78,7 +75,7 @@ describe GRPC::RpcDesc do
it 'absorbs EventError with no further action' do it 'absorbs EventError with no further action' do
expect(@call).to receive(:remote_read).once.and_raise(EventError) expect(@call).to receive(:remote_read).once.and_raise(EventError)
blk = Proc.new do blk = proc do
@request_response.run_server_method(@call, method(:fake_reqresp)) @request_response.run_server_method(@call, method(:fake_reqresp))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -86,7 +83,7 @@ describe GRPC::RpcDesc do
it 'absorbs CallError with no further action' do it 'absorbs CallError with no further action' do
expect(@call).to receive(:remote_read).once.and_raise(CallError) expect(@call).to receive(:remote_read).once.and_raise(CallError)
blk = Proc.new do blk = proc do
@request_response.run_server_method(@call, method(:fake_reqresp)) @request_response.run_server_method(@call, method(:fake_reqresp))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -100,7 +97,6 @@ describe GRPC::RpcDesc do
expect(@call).to receive(:finished).once expect(@call).to receive(:finished).once
@request_response.run_server_method(@call, method(:fake_reqresp)) @request_response.run_server_method(@call, method(:fake_reqresp))
end end
end end
describe 'for client streamers' do describe 'for client streamers' do
@ -122,7 +118,7 @@ describe GRPC::RpcDesc do
it 'absorbs EventError with no further action' do it 'absorbs EventError with no further action' do
expect(@call).to receive(:remote_send).once.and_raise(EventError) expect(@call).to receive(:remote_send).once.and_raise(EventError)
blk = Proc.new do blk = proc do
@client_streamer.run_server_method(@call, method(:fake_clstream)) @client_streamer.run_server_method(@call, method(:fake_clstream))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -130,20 +126,18 @@ describe GRPC::RpcDesc do
it 'absorbs CallError with no further action' do it 'absorbs CallError with no further action' do
expect(@call).to receive(:remote_send).once.and_raise(CallError) expect(@call).to receive(:remote_send).once.and_raise(CallError)
blk = Proc.new do blk = proc do
@client_streamer.run_server_method(@call, method(:fake_clstream)) @client_streamer.run_server_method(@call, method(:fake_clstream))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
it 'sends a response and closes the stream if there no errors' do it 'sends a response and closes the stream if there no errors' do
req = Object.new
expect(@call).to receive(:remote_send).once.with(@ok_response) expect(@call).to receive(:remote_send).once.with(@ok_response)
expect(@call).to receive(:send_status).once.with(OK, 'OK') expect(@call).to receive(:send_status).once.with(OK, 'OK')
expect(@call).to receive(:finished).once expect(@call).to receive(:finished).once
@client_streamer.run_server_method(@call, method(:fake_clstream)) @client_streamer.run_server_method(@call, method(:fake_clstream))
end end
end end
describe 'for server streaming' do describe 'for server streaming' do
@ -167,7 +161,7 @@ describe GRPC::RpcDesc do
it 'absorbs EventError with no further action' do it 'absorbs EventError with no further action' do
expect(@call).to receive(:remote_read).once.and_raise(EventError) expect(@call).to receive(:remote_read).once.and_raise(EventError)
blk = Proc.new do blk = proc do
@server_streamer.run_server_method(@call, method(:fake_svstream)) @server_streamer.run_server_method(@call, method(:fake_svstream))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -175,7 +169,7 @@ describe GRPC::RpcDesc do
it 'absorbs CallError with no further action' do it 'absorbs CallError with no further action' do
expect(@call).to receive(:remote_read).once.and_raise(CallError) expect(@call).to receive(:remote_read).once.and_raise(CallError)
blk = Proc.new do blk = proc do
@server_streamer.run_server_method(@call, method(:fake_svstream)) @server_streamer.run_server_method(@call, method(:fake_svstream))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -189,7 +183,6 @@ describe GRPC::RpcDesc do
expect(@call).to receive(:finished).once expect(@call).to receive(:finished).once
@server_streamer.run_server_method(@call, method(:fake_svstream)) @server_streamer.run_server_method(@call, method(:fake_svstream))
end end
end end
describe 'for bidi streamers' do describe 'for bidi streamers' do
@ -215,30 +208,27 @@ describe GRPC::RpcDesc do
end end
it 'closes the stream if there no errors' do it 'closes the stream if there no errors' do
req = Object.new
expect(@call).to receive(:run_server_bidi) expect(@call).to receive(:run_server_bidi)
expect(@call).to receive(:send_status).once.with(OK, 'OK') expect(@call).to receive(:send_status).once.with(OK, 'OK')
expect(@call).to receive(:finished).once expect(@call).to receive(:finished).once
@bidi_streamer.run_server_method(@call, method(:fake_bidistream)) @bidi_streamer.run_server_method(@call, method(:fake_bidistream))
end end
end end
end end
describe '#assert_arity_matches' do describe '#assert_arity_matches' do
def no_arg def no_arg
end end
def fake_clstream(arg) def fake_clstream(_arg)
end end
def fake_svstream(arg1, arg2) def fake_svstream(_arg1, _arg2)
end end
it 'raises when a request_response does not have 2 args' do it 'raises when a request_response does not have 2 args' do
[:fake_clstream, :no_arg].each do |mth| [:fake_clstream, :no_arg].each do |mth|
blk = Proc.new do blk = proc do
@request_response.assert_arity_matches(method(mth)) @request_response.assert_arity_matches(method(mth))
end end
expect(&blk).to raise_error expect(&blk).to raise_error
@ -246,7 +236,7 @@ describe GRPC::RpcDesc do
end end
it 'passes when a request_response has 2 args' do it 'passes when a request_response has 2 args' do
blk = Proc.new do blk = proc do
@request_response.assert_arity_matches(method(:fake_svstream)) @request_response.assert_arity_matches(method(:fake_svstream))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -254,7 +244,7 @@ describe GRPC::RpcDesc do
it 'raises when a server_streamer does not have 2 args' do it 'raises when a server_streamer does not have 2 args' do
[:fake_clstream, :no_arg].each do |mth| [:fake_clstream, :no_arg].each do |mth|
blk = Proc.new do blk = proc do
@server_streamer.assert_arity_matches(method(mth)) @server_streamer.assert_arity_matches(method(mth))
end end
expect(&blk).to raise_error expect(&blk).to raise_error
@ -262,7 +252,7 @@ describe GRPC::RpcDesc do
end end
it 'passes when a server_streamer has 2 args' do it 'passes when a server_streamer has 2 args' do
blk = Proc.new do blk = proc do
@server_streamer.assert_arity_matches(method(:fake_svstream)) @server_streamer.assert_arity_matches(method(:fake_svstream))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -270,7 +260,7 @@ describe GRPC::RpcDesc do
it 'raises when a client streamer does not have 1 arg' do it 'raises when a client streamer does not have 1 arg' do
[:fake_svstream, :no_arg].each do |mth| [:fake_svstream, :no_arg].each do |mth|
blk = Proc.new do blk = proc do
@client_streamer.assert_arity_matches(method(mth)) @client_streamer.assert_arity_matches(method(mth))
end end
expect(&blk).to raise_error expect(&blk).to raise_error
@ -278,16 +268,15 @@ describe GRPC::RpcDesc do
end end
it 'passes when a client_streamer has 1 arg' do it 'passes when a client_streamer has 1 arg' do
blk = Proc.new do blk = proc do
@client_streamer.assert_arity_matches(method(:fake_clstream)) @client_streamer.assert_arity_matches(method(:fake_clstream))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
it 'raises when a bidi streamer does not have 1 arg' do it 'raises when a bidi streamer does not have 1 arg' do
[:fake_svstream, :no_arg].each do |mth| [:fake_svstream, :no_arg].each do |mth|
blk = Proc.new do blk = proc do
@bidi_streamer.assert_arity_matches(method(mth)) @bidi_streamer.assert_arity_matches(method(mth))
end end
expect(&blk).to raise_error expect(&blk).to raise_error
@ -295,88 +284,78 @@ describe GRPC::RpcDesc do
end end
it 'passes when a bidi streamer has 1 arg' do it 'passes when a bidi streamer has 1 arg' do
blk = Proc.new do blk = proc do
@bidi_streamer.assert_arity_matches(method(:fake_clstream)) @bidi_streamer.assert_arity_matches(method(:fake_clstream))
end end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
end end
describe '#is_request_response?' do describe '#request_response?' do
it 'is true only input and output are both not Streams' do it 'is true only input and output are both not Streams' do
expect(@request_response.is_request_response?).to be(true) expect(@request_response.request_response?).to be(true)
expect(@client_streamer.is_request_response?).to be(false) expect(@client_streamer.request_response?).to be(false)
expect(@bidi_streamer.is_request_response?).to be(false) expect(@bidi_streamer.request_response?).to be(false)
expect(@server_streamer.is_request_response?).to be(false) expect(@server_streamer.request_response?).to be(false)
end end
end end
describe '#is_client_streamer?' do describe '#client_streamer?' do
it 'is true only when input is a Stream and output is not a Stream' do it 'is true only when input is a Stream and output is not a Stream' do
expect(@client_streamer.is_client_streamer?).to be(true) expect(@client_streamer.client_streamer?).to be(true)
expect(@request_response.is_client_streamer?).to be(false) expect(@request_response.client_streamer?).to be(false)
expect(@server_streamer.is_client_streamer?).to be(false) expect(@server_streamer.client_streamer?).to be(false)
expect(@bidi_streamer.is_client_streamer?).to be(false) expect(@bidi_streamer.client_streamer?).to be(false)
end end
end end
describe '#is_server_streamer?' do describe '#server_streamer?' do
it 'is true only when output is a Stream and input is not a Stream' do it 'is true only when output is a Stream and input is not a Stream' do
expect(@server_streamer.is_server_streamer?).to be(true) expect(@server_streamer.server_streamer?).to be(true)
expect(@client_streamer.is_server_streamer?).to be(false) expect(@client_streamer.server_streamer?).to be(false)
expect(@request_response.is_server_streamer?).to be(false) expect(@request_response.server_streamer?).to be(false)
expect(@bidi_streamer.is_server_streamer?).to be(false) expect(@bidi_streamer.server_streamer?).to be(false)
end end
end end
describe '#is_bidi_streamer?' do describe '#bidi_streamer?' do
it 'is true only when output is a Stream and input is a Stream' do it 'is true only when output is a Stream and input is a Stream' do
expect(@bidi_streamer.is_bidi_streamer?).to be(true) expect(@bidi_streamer.bidi_streamer?).to be(true)
expect(@server_streamer.is_bidi_streamer?).to be(false) expect(@server_streamer.bidi_streamer?).to be(false)
expect(@client_streamer.is_bidi_streamer?).to be(false) expect(@client_streamer.bidi_streamer?).to be(false)
expect(@request_response.is_bidi_streamer?).to be(false) expect(@request_response.bidi_streamer?).to be(false)
end end
end end
def fake_reqresp(req, call) def fake_reqresp(_req, _call)
@ok_response @ok_response
end end
def fake_clstream(call) def fake_clstream(_call)
@ok_response @ok_response
end end
def fake_svstream(req, call) def fake_svstream(_req, _call)
[@ok_response, @ok_response] [@ok_response, @ok_response]
end end
def fake_bidistream(an_array) def fake_bidistream(an_array)
return an_array an_array
end end
def bad_status(req, call) def bad_status(_req, _call)
raise GRPC::BadStatus.new(@bs_code, 'NOK') fail GRPC::BadStatus.new(@bs_code, 'NOK')
end end
def other_error(req, call) def other_error(_req, _call)
raise ArgumentError.new('other error') fail(ArgumentError, 'other error')
end end
def bad_status_alt(call) def bad_status_alt(_call)
raise GRPC::BadStatus.new(@bs_code, 'NOK') fail GRPC::BadStatus.new(@bs_code, 'NOK')
end end
def other_error_alt(call) def other_error_alt(_call)
raise ArgumentError.new('other error') fail(ArgumentError, 'other error')
end end
end end

@ -33,9 +33,7 @@ require 'xray/thread_dump_signal_handler'
Pool = GRPC::RpcServer::Pool Pool = GRPC::RpcServer::Pool
describe Pool do describe Pool do
describe '#new' do describe '#new' do
it 'raises if a non-positive size is used' do it 'raises if a non-positive size is used' do
expect { Pool.new(0) }.to raise_error expect { Pool.new(0) }.to raise_error
expect { Pool.new(-1) }.to raise_error expect { Pool.new(-1) }.to raise_error
@ -45,11 +43,9 @@ describe Pool do
it 'is constructed OK with a positive size' do it 'is constructed OK with a positive size' do
expect { Pool.new(1) }.not_to raise_error expect { Pool.new(1) }.not_to raise_error
end end
end end
describe '#jobs_waiting' do describe '#jobs_waiting' do
it 'at start, it is zero' do it 'at start, it is zero' do
p = Pool.new(1) p = Pool.new(1)
expect(p.jobs_waiting).to be(0) expect(p.jobs_waiting).to be(0)
@ -57,74 +53,67 @@ describe Pool do
it 'it increases, with each scheduled job if the pool is not running' do it 'it increases, with each scheduled job if the pool is not running' do
p = Pool.new(1) p = Pool.new(1)
job = Proc.new { } job = proc {}
expect(p.jobs_waiting).to be(0) expect(p.jobs_waiting).to be(0)
5.times do |i| 5.times do |i|
p.schedule(&job) p.schedule(&job)
expect(p.jobs_waiting).to be(i + 1) expect(p.jobs_waiting).to be(i + 1)
end end
end end
it 'it decreases as jobs are run' do it 'it decreases as jobs are run' do
p = Pool.new(1) p = Pool.new(1)
job = Proc.new { } job = proc {}
expect(p.jobs_waiting).to be(0) expect(p.jobs_waiting).to be(0)
3.times do |i| 3.times do
p.schedule(&job) p.schedule(&job)
end end
p.start p.start
sleep 2 sleep 2
expect(p.jobs_waiting).to be(0) expect(p.jobs_waiting).to be(0)
end end
end end
describe '#schedule' do describe '#schedule' do
it 'throws if the pool is already stopped' do it 'throws if the pool is already stopped' do
p = Pool.new(1) p = Pool.new(1)
p.stop() p.stop
job = Proc.new { } job = proc {}
expect { p.schedule(&job) }.to raise_error expect { p.schedule(&job) }.to raise_error
end end
it 'adds jobs that get run by the pool' do it 'adds jobs that get run by the pool' do
p = Pool.new(1) p = Pool.new(1)
p.start() p.start
o, q = Object.new, Queue.new o, q = Object.new, Queue.new
job = Proc.new { q.push(o) } job = proc { q.push(o) }
p.schedule(&job) p.schedule(&job)
expect(q.pop).to be(o) expect(q.pop).to be(o)
p.stop p.stop
end end
end end
describe '#stop' do describe '#stop' do
it 'works when there are no scheduled tasks' do it 'works when there are no scheduled tasks' do
p = Pool.new(1) p = Pool.new(1)
expect { p.stop() }.not_to raise_error expect { p.stop }.not_to raise_error
end end
it 'stops jobs when there are long running jobs' do it 'stops jobs when there are long running jobs' do
p = Pool.new(1) p = Pool.new(1)
p.start() p.start
o, q = Object.new, Queue.new o, q = Object.new, Queue.new
job = Proc.new do job = proc do
sleep(5) # long running sleep(5) # long running
q.push(o) q.push(o)
end end
p.schedule(&job) p.schedule(&job)
sleep(1) # should ensure the long job gets scheduled sleep(1) # should ensure the long job gets scheduled
expect { p.stop() }.not_to raise_error expect { p.stop }.not_to raise_error
end end
end end
describe '#start' do describe '#start' do
it 'runs pre-scheduled jobs' do it 'runs pre-scheduled jobs' do
p = Pool.new(2) p = Pool.new(2)
o, q = Object.new, Queue.new o, q = Object.new, Queue.new
@ -146,7 +135,5 @@ describe Pool do
end end
p.stop p.stop
end end
end end
end end

@ -37,33 +37,37 @@ def load_test_certs
files.map { |f| File.open(File.join(test_root, f)).read } files.map { |f| File.open(File.join(test_root, f)).read }
end end
# A test message
class EchoMsg class EchoMsg
def self.marshal(o) def self.marshal(_o)
'' ''
end end
def self.unmarshal(o) def self.unmarshal(_o)
EchoMsg.new EchoMsg.new
end end
end end
# A test service with no methods.
class EmptyService class EmptyService
include GRPC::GenericService include GRPC::GenericService
end end
# A test service without an implementation.
class NoRpcImplementation class NoRpcImplementation
include GRPC::GenericService include GRPC::GenericService
rpc :an_rpc, EchoMsg, EchoMsg rpc :an_rpc, EchoMsg, EchoMsg
end end
# A test service with an implementation.
class EchoService class EchoService
include GRPC::GenericService include GRPC::GenericService
rpc :an_rpc, EchoMsg, EchoMsg rpc :an_rpc, EchoMsg, EchoMsg
def initialize(default_var='ignored') def initialize(_default_var = 'ignored')
end end
def an_rpc(req, call) def an_rpc(req, _call)
logger.info('echo service received a request') logger.info('echo service received a request')
req req
end end
@ -71,14 +75,15 @@ end
EchoStub = EchoService.rpc_stub_class EchoStub = EchoService.rpc_stub_class
# A slow test service.
class SlowService class SlowService
include GRPC::GenericService include GRPC::GenericService
rpc :an_rpc, EchoMsg, EchoMsg rpc :an_rpc, EchoMsg, EchoMsg
def initialize(default_var='ignored') def initialize(_default_var = 'ignored')
end end
def an_rpc(req, call) def an_rpc(req, _call)
delay = 0.25 delay = 0.25
logger.info("starting a slow #{delay} rpc") logger.info("starting a slow #{delay} rpc")
sleep delay sleep delay
@ -89,7 +94,6 @@ end
SlowStub = SlowService.rpc_stub_class SlowStub = SlowService.rpc_stub_class
describe GRPC::RpcServer do describe GRPC::RpcServer do
RpcServer = GRPC::RpcServer RpcServer = GRPC::RpcServer
StatusCodes = GRPC::Core::StatusCodes StatusCodes = GRPC::Core::StatusCodes
@ -97,7 +101,7 @@ describe GRPC::RpcServer do
@method = 'an_rpc_method' @method = 'an_rpc_method'
@pass = 0 @pass = 0
@fail = 1 @fail = 1
@noop = Proc.new { |x| x } @noop = proc { |x| x }
@server_queue = GRPC::Core::CompletionQueue.new @server_queue = GRPC::Core::CompletionQueue.new
port = find_unused_tcp_port port = find_unused_tcp_port
@ -112,18 +116,17 @@ describe GRPC::RpcServer do
end end
describe '#new' do describe '#new' do
it 'can be created with just some args' do it 'can be created with just some args' do
opts = {:a_channel_arg => 'an_arg'} opts = { a_channel_arg: 'an_arg' }
blk = Proc.new do blk = proc do
RpcServer.new(**opts) RpcServer.new(**opts)
end end
expect(&blk).not_to raise_error expect(&blk).not_to raise_error
end end
it 'can be created with a default deadline' do it 'can be created with a default deadline' do
opts = {:a_channel_arg => 'an_arg', :deadline => 5} opts = { a_channel_arg: 'an_arg', deadline: 5 }
blk = Proc.new do blk = proc do
RpcServer.new(**opts) RpcServer.new(**opts)
end end
expect(&blk).not_to raise_error expect(&blk).not_to raise_error
@ -131,20 +134,20 @@ describe GRPC::RpcServer do
it 'can be created with a completion queue override' do it 'can be created with a completion queue override' do
opts = { opts = {
:a_channel_arg => 'an_arg', a_channel_arg: 'an_arg',
:completion_queue_override => @server_queue completion_queue_override: @server_queue
} }
blk = Proc.new do blk = proc do
RpcServer.new(**opts) RpcServer.new(**opts)
end end
expect(&blk).not_to raise_error expect(&blk).not_to raise_error
end end
it 'cannot be created with a bad completion queue override' do it 'cannot be created with a bad completion queue override' do
blk = Proc.new do blk = proc do
opts = { opts = {
:a_channel_arg => 'an_arg', a_channel_arg: 'an_arg',
:completion_queue_override => Object.new completion_queue_override: Object.new
} }
RpcServer.new(**opts) RpcServer.new(**opts)
end end
@ -152,10 +155,10 @@ describe GRPC::RpcServer do
end end
it 'cannot be created with invalid ServerCredentials' do it 'cannot be created with invalid ServerCredentials' do
blk = Proc.new do blk = proc do
opts = { opts = {
:a_channel_arg => 'an_arg', a_channel_arg: 'an_arg',
:creds => Object.new creds: Object.new
} }
RpcServer.new(**opts) RpcServer.new(**opts)
end end
@ -165,10 +168,10 @@ describe GRPC::RpcServer do
it 'can be created with the creds as valid ServerCedentials' do it 'can be created with the creds as valid ServerCedentials' do
certs = load_test_certs certs = load_test_certs
server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
blk = Proc.new do blk = proc do
opts = { opts = {
:a_channel_arg => 'an_arg', a_channel_arg: 'an_arg',
:creds => server_creds creds: server_creds
} }
RpcServer.new(**opts) RpcServer.new(**opts)
end end
@ -176,30 +179,28 @@ describe GRPC::RpcServer do
end end
it 'can be created with a server override' do it 'can be created with a server override' do
opts = {:a_channel_arg => 'an_arg', :server_override => @server} opts = { a_channel_arg: 'an_arg', server_override: @server }
blk = Proc.new do blk = proc do
RpcServer.new(**opts) RpcServer.new(**opts)
end end
expect(&blk).not_to raise_error expect(&blk).not_to raise_error
end end
it 'cannot be created with a bad server override' do it 'cannot be created with a bad server override' do
blk = Proc.new do blk = proc do
opts = { opts = {
:a_channel_arg => 'an_arg', a_channel_arg: 'an_arg',
:server_override => Object.new server_override: Object.new
} }
RpcServer.new(**opts) RpcServer.new(**opts)
end end
expect(&blk).to raise_error expect(&blk).to raise_error
end end
end end
describe '#stopped?' do describe '#stopped?' do
before(:each) do before(:each) do
opts = {:a_channel_arg => 'an_arg', :poll_period => 1} opts = { a_channel_arg: 'an_arg', poll_period: 1 }
@srv = RpcServer.new(**opts) @srv = RpcServer.new(**opts)
end end
@ -229,33 +230,31 @@ describe GRPC::RpcServer do
expect(@srv.stopped?).to be(true) expect(@srv.stopped?).to be(true)
t.join t.join
end end
end end
describe '#running?' do describe '#running?' do
it 'starts out false' do it 'starts out false' do
opts = {:a_channel_arg => 'an_arg', :server_override => @server} opts = { a_channel_arg: 'an_arg', server_override: @server }
r = RpcServer.new(**opts) r = RpcServer.new(**opts)
expect(r.running?).to be(false) expect(r.running?).to be(false)
end end
it 'is false after run is called with no services registered' do it 'is false after run is called with no services registered' do
opts = { opts = {
:a_channel_arg => 'an_arg', a_channel_arg: 'an_arg',
:poll_period => 1, poll_period: 1,
:server_override => @server server_override: @server
} }
r = RpcServer.new(**opts) r = RpcServer.new(**opts)
r.run() r.run
expect(r.running?).to be(false) expect(r.running?).to be(false)
end end
it 'is true after run is called with a registered service' do it 'is true after run is called with a registered service' do
opts = { opts = {
:a_channel_arg => 'an_arg', a_channel_arg: 'an_arg',
:poll_period => 1, poll_period: 1,
:server_override => @server server_override: @server
} }
r = RpcServer.new(**opts) r = RpcServer.new(**opts)
r.handle(EchoService) r.handle(EchoService)
@ -265,13 +264,11 @@ describe GRPC::RpcServer do
r.stop r.stop
t.join t.join
end end
end end
describe '#handle' do describe '#handle' do
before(:each) do before(:each) do
@opts = {:a_channel_arg => 'an_arg', :poll_period => 1} @opts = { a_channel_arg: 'an_arg', poll_period: 1 }
@srv = RpcServer.new(**@opts) @srv = RpcServer.new(**@opts)
end end
@ -309,33 +306,30 @@ describe GRPC::RpcServer do
@srv.handle(EchoService) @srv.handle(EchoService)
expect { r.handle(EchoService) }.to raise_error expect { r.handle(EchoService) }.to raise_error
end end
end end
describe '#run' do describe '#run' do
before(:each) do before(:each) do
@client_opts = { @client_opts = {
:channel_override => @ch channel_override: @ch
} }
@marshal = EchoService.rpc_descs[:an_rpc].marshal_proc @marshal = EchoService.rpc_descs[:an_rpc].marshal_proc
@unmarshal = EchoService.rpc_descs[:an_rpc].unmarshal_proc(:output) @unmarshal = EchoService.rpc_descs[:an_rpc].unmarshal_proc(:output)
server_opts = { server_opts = {
:server_override => @server, server_override: @server,
:completion_queue_override => @server_queue, completion_queue_override: @server_queue,
:poll_period => 1 poll_period: 1
} }
@srv = RpcServer.new(**server_opts) @srv = RpcServer.new(**server_opts)
end end
describe 'when running' do describe 'when running' do
it 'should return NOT_FOUND status for requests on unknown methods' do it 'should return NOT_FOUND status for requests on unknown methods' do
@srv.handle(EchoService) @srv.handle(EchoService)
t = Thread.new { @srv.run } t = Thread.new { @srv.run }
@srv.wait_till_running @srv.wait_till_running
req = EchoMsg.new req = EchoMsg.new
blk = Proc.new do blk = proc do
cq = GRPC::Core::CompletionQueue.new cq = GRPC::Core::CompletionQueue.new
stub = GRPC::ClientStub.new(@host, cq, **@client_opts) stub = GRPC::ClientStub.new(@host, cq, **@client_opts)
stub.request_response('/unknown', req, @marshal, @unmarshal) stub.request_response('/unknown', req, @marshal, @unmarshal)
@ -352,20 +346,19 @@ describe GRPC::RpcServer do
req = EchoMsg.new req = EchoMsg.new
n = 5 # arbitrary n = 5 # arbitrary
stub = EchoStub.new(@host, **@client_opts) stub = EchoStub.new(@host, **@client_opts)
n.times { |x| expect(stub.an_rpc(req)).to be_a(EchoMsg) } n.times { expect(stub.an_rpc(req)).to be_a(EchoMsg) }
@srv.stop @srv.stop
t.join t.join
end end
it 'should obtain responses for multiple parallel requests' do it 'should obtain responses for multiple parallel requests' do
@srv.handle(EchoService) @srv.handle(EchoService)
t = Thread.new { @srv.run } Thread.new { @srv.run }
@srv.wait_till_running @srv.wait_till_running
req, q = EchoMsg.new, Queue.new req, q = EchoMsg.new, Queue.new
n = 5 # arbitrary n = 5 # arbitrary
threads = [] threads = []
n.times do |x| n.times do
cq = GRPC::Core::CompletionQueue.new
threads << Thread.new do threads << Thread.new do
stub = EchoStub.new(@host, **@client_opts) stub = EchoStub.new(@host, **@client_opts)
q << stub.an_rpc(req) q << stub.an_rpc(req)
@ -373,44 +366,40 @@ describe GRPC::RpcServer do
end end
n.times { expect(q.pop).to be_a(EchoMsg) } n.times { expect(q.pop).to be_a(EchoMsg) }
@srv.stop @srv.stop
threads.each { |t| t.join } threads.each(&:join)
end end
it 'should return UNAVAILABLE status if there too many jobs' do it 'should return UNAVAILABLE status if there too many jobs' do
opts = { opts = {
:a_channel_arg => 'an_arg', a_channel_arg: 'an_arg',
:server_override => @server, server_override: @server,
:completion_queue_override => @server_queue, completion_queue_override: @server_queue,
:pool_size => 1, pool_size: 1,
:poll_period => 1, poll_period: 1,
:max_waiting_requests => 0 max_waiting_requests: 0
} }
alt_srv = RpcServer.new(**opts) alt_srv = RpcServer.new(**opts)
alt_srv.handle(SlowService) alt_srv.handle(SlowService)
t = Thread.new { alt_srv.run } Thread.new { alt_srv.run }
alt_srv.wait_till_running alt_srv.wait_till_running
req = EchoMsg.new req = EchoMsg.new
n = 5 # arbitrary, use as many to ensure the server pool is exceeded n = 5 # arbitrary, use as many to ensure the server pool is exceeded
threads = [] threads = []
_1_failed_as_unavailable = false one_failed_as_unavailable = false
n.times do |x| n.times do
threads << Thread.new do threads << Thread.new do
cq = GRPC::Core::CompletionQueue.new
stub = SlowStub.new(@host, **@client_opts) stub = SlowStub.new(@host, **@client_opts)
begin begin
stub.an_rpc(req) stub.an_rpc(req)
rescue GRPC::BadStatus => e rescue GRPC::BadStatus => e
_1_failed_as_unavailable = e.code == StatusCodes::UNAVAILABLE one_failed_as_unavailable = e.code == StatusCodes::UNAVAILABLE
end end
end end
end end
threads.each { |t| t.join } threads.each(&:join)
alt_srv.stop alt_srv.stop
expect(_1_failed_as_unavailable).to be(true) expect(one_failed_as_unavailable).to be(true)
end end
end end
end end
end end

@ -31,23 +31,24 @@ require 'grpc'
require 'grpc/generic/rpc_desc' require 'grpc/generic/rpc_desc'
require 'grpc/generic/service' require 'grpc/generic/service'
# A test message that encodes/decodes using marshal/marshal.
class GoodMsg class GoodMsg
def self.marshal(o) def self.marshal(_o)
'' ''
end end
def self.unmarshal(o) def self.unmarshal(_o)
GoodMsg.new GoodMsg.new
end end
end end
# A test message that encodes/decodes using encode/decode.
class EncodeDecodeMsg class EncodeDecodeMsg
def self.encode(o) def self.encode(_o)
'' ''
end end
def self.decode(o) def self.decode(_o)
GoodMsg.new GoodMsg.new
end end
end end
@ -55,7 +56,6 @@ end
GenericService = GRPC::GenericService GenericService = GRPC::GenericService
Dsl = GenericService::Dsl Dsl = GenericService::Dsl
describe 'String#underscore' do describe 'String#underscore' do
it 'should convert CamelCase to underscore separated' do it 'should convert CamelCase to underscore separated' do
expect('AnRPC'.underscore).to eq('an_rpc') expect('AnRPC'.underscore).to eq('an_rpc')
@ -66,20 +66,14 @@ describe 'String#underscore' do
end end
describe Dsl do describe Dsl do
it 'can be included in new classes' do it 'can be included in new classes' do
blk = Proc.new do blk = proc { Class.new { include Dsl } }
c = Class.new { include Dsl }
end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
end end
describe GenericService do describe GenericService do
describe 'including it' do describe 'including it' do
it 'adds a class method, rpc' do it 'adds a class method, rpc' do
c = Class.new do c = Class.new do
include GenericService include GenericService
@ -144,9 +138,8 @@ describe GenericService do
end end
describe '#include' do describe '#include' do
it 'raises if #rpc is missing an arg' do it 'raises if #rpc is missing an arg' do
blk = Proc.new do blk = proc do
Class.new do Class.new do
include GenericService include GenericService
rpc :AnRpc, GoodMsg rpc :AnRpc, GoodMsg
@ -154,7 +147,7 @@ describe GenericService do
end end
expect(&blk).to raise_error ArgumentError expect(&blk).to raise_error ArgumentError
blk = Proc.new do blk = proc do
Class.new do Class.new do
include GenericService include GenericService
rpc :AnRpc rpc :AnRpc
@ -164,9 +157,8 @@ describe GenericService do
end end
describe 'when #rpc args are incorrect' do describe 'when #rpc args are incorrect' do
it 'raises if an arg does not have the marshal or unmarshal methods' do it 'raises if an arg does not have the marshal or unmarshal methods' do
blk = Proc.new do blk = proc do
Class.new do Class.new do
include GenericService include GenericService
rpc :AnRpc, GoodMsg, Object rpc :AnRpc, GoodMsg, Object
@ -176,13 +168,14 @@ describe GenericService do
end end
it 'raises if a type arg only has the marshal method' do it 'raises if a type arg only has the marshal method' do
# a bad message type with only a marshal method
class OnlyMarshal class OnlyMarshal
def marshal(o) def marshal(o)
o o
end end
end end
blk = Proc.new do blk = proc do
Class.new do Class.new do
include GenericService include GenericService
rpc :AnRpc, OnlyMarshal, GoodMsg rpc :AnRpc, OnlyMarshal, GoodMsg
@ -192,12 +185,13 @@ describe GenericService do
end end
it 'raises if a type arg only has the unmarshal method' do it 'raises if a type arg only has the unmarshal method' do
# a bad message type with only an unmarshal method
class OnlyUnmarshal class OnlyUnmarshal
def self.ummarshal(o) def self.ummarshal(o)
o o
end end
end end
blk = Proc.new do blk = proc do
Class.new do Class.new do
include GenericService include GenericService
rpc :AnRpc, GoodMsg, OnlyUnmarshal rpc :AnRpc, GoodMsg, OnlyUnmarshal
@ -208,7 +202,7 @@ describe GenericService do
end end
it 'is ok for services that expect the default {un,}marshal methods' do it 'is ok for services that expect the default {un,}marshal methods' do
blk = Proc.new do blk = proc do
Class.new do Class.new do
include GenericService include GenericService
rpc :AnRpc, GoodMsg, GoodMsg rpc :AnRpc, GoodMsg, GoodMsg
@ -218,7 +212,7 @@ describe GenericService do
end end
it 'is ok for services that override the default {un,}marshal methods' do it 'is ok for services that override the default {un,}marshal methods' do
blk = Proc.new do blk = proc do
Class.new do Class.new do
include GenericService include GenericService
self.marshal_class_method = :encode self.marshal_class_method = :encode
@ -228,11 +222,9 @@ describe GenericService do
end end
expect(&blk).not_to raise_error expect(&blk).not_to raise_error
end end
end end
describe '#rpc_stub_class' do describe '#rpc_stub_class' do
it 'generates a client class that defines any of the rpc methods' do it 'generates a client class that defines any of the rpc methods' do
s = Class.new do s = Class.new do
include GenericService include GenericService
@ -249,7 +241,6 @@ describe GenericService do
end end
describe 'the generated instances' do describe 'the generated instances' do
it 'can be instanciated with just a hostname' do it 'can be instanciated with just a hostname' do
s = Class.new do s = Class.new do
include GenericService include GenericService
@ -277,13 +268,10 @@ describe GenericService do
expect(o.methods).to include(:a_client_streamer) expect(o.methods).to include(:a_client_streamer)
expect(o.methods).to include(:a_bidi_streamer) expect(o.methods).to include(:a_bidi_streamer)
end end
end end
end end
describe '#assert_rpc_descs_have_methods' do describe '#assert_rpc_descs_have_methods' do
it 'fails if there is no instance method for an rpc descriptor' do it 'fails if there is no instance method for an rpc descriptor' do
c1 = Class.new do c1 = Class.new do
include GenericService include GenericService
@ -310,16 +298,16 @@ describe GenericService do
rpc :AClientStreamer, stream(GoodMsg), GoodMsg rpc :AClientStreamer, stream(GoodMsg), GoodMsg
rpc :ABidiStreamer, stream(GoodMsg), stream(GoodMsg) rpc :ABidiStreamer, stream(GoodMsg), stream(GoodMsg)
def an_rpc(req, call) def an_rpc(_req, _call)
end end
def a_server_streamer(req, call) def a_server_streamer(_req, _call)
end end
def a_client_streamer(call) def a_client_streamer(_call)
end end
def a_bidi_streamer(call) def a_bidi_streamer(_call)
end end
end end
expect { c.assert_rpc_descs_have_methods }.to_not raise_error expect { c.assert_rpc_descs_have_methods }.to_not raise_error
@ -330,7 +318,7 @@ describe GenericService do
include GenericService include GenericService
rpc :AnRpc, GoodMsg, GoodMsg rpc :AnRpc, GoodMsg, GoodMsg
def an_rpc(req, call) def an_rpc(_req, _call)
end end
end end
c = Class.new(base) c = Class.new(base)
@ -344,13 +332,11 @@ describe GenericService do
rpc :AnRpc, GoodMsg, GoodMsg rpc :AnRpc, GoodMsg, GoodMsg
end end
c = Class.new(base) do c = Class.new(base) do
def an_rpc(req, call) def an_rpc(_req, _call)
end end
end end
expect { c.assert_rpc_descs_have_methods }.to_not raise_error expect { c.assert_rpc_descs_have_methods }.to_not raise_error
expect(c.include?(GenericService)).to be(true) expect(c.include?(GenericService)).to be(true)
end end
end end
end end

@ -30,7 +30,6 @@
require 'grpc' require 'grpc'
describe GRPC::Core::Metadata do describe GRPC::Core::Metadata do
describe '#new' do describe '#new' do
it 'should create instances' do it 'should create instances' do
expect { GRPC::Core::Metadata.new('a key', 'a value') }.to_not raise_error expect { GRPC::Core::Metadata.new('a key', 'a value') }.to_not raise_error
@ -62,5 +61,4 @@ describe GRPC::Core::Metadata do
expect(md.dup.value).to eq('a value') expect(md.dup.value).to eq('a value')
end end
end end
end end

@ -32,7 +32,7 @@ require 'socket'
# @param [Fixnum] the minimum port number to accept # @param [Fixnum] the minimum port number to accept
# @param [Fixnum] the maximum port number to accept # @param [Fixnum] the maximum port number to accept
# @return [Fixnum ]a free tcp port # @return [Fixnum ]a free tcp port
def find_unused_tcp_port(min=32768, max=60000) def find_unused_tcp_port(min = 32_768, max = 60_000)
# Allow the system to assign a port, by specifying 0. # Allow the system to assign a port, by specifying 0.
# Loop until a port is assigned in the required range # Loop until a port is assigned in the required range
loop do loop do
@ -40,6 +40,6 @@ def find_unused_tcp_port(min=32768, max=60000)
socket.bind(Addrinfo.tcp('127.0.0.1', 0)) socket.bind(Addrinfo.tcp('127.0.0.1', 0))
p = socket.local_address.ip_port p = socket.local_address.ip_port
socket.close socket.close
return p if p > min and p < 60000 return p if p > min && p < max
end end
end end

@ -35,13 +35,10 @@ def load_test_certs
files.map { |f| File.open(File.join(test_root, f)).read } files.map { |f| File.open(File.join(test_root, f)).read }
end end
describe GRPC::Core::ServerCredentials do describe GRPC::Core::ServerCredentials do
Creds = GRPC::Core::ServerCredentials Creds = GRPC::Core::ServerCredentials
describe '#new' do describe '#new' do
it 'can be constructed from a fake CA PEM, server PEM and a server key' do it 'can be constructed from a fake CA PEM, server PEM and a server key' do
expect { Creds.new('a', 'b', 'c') }.not_to raise_error expect { Creds.new('a', 'b', 'c') }.not_to raise_error
end end
@ -53,22 +50,20 @@ describe GRPC::Core::ServerCredentials do
it 'cannot be constructed without a server cert chain' do it 'cannot be constructed without a server cert chain' do
root_cert, server_key, _ = load_test_certs root_cert, server_key, _ = load_test_certs
blk = Proc.new { Creds.new(root_cert, server_key, nil) } blk = proc { Creds.new(root_cert, server_key, nil) }
expect(&blk).to raise_error expect(&blk).to raise_error
end end
it 'cannot be constructed without a server key' do it 'cannot be constructed without a server key' do
root_cert, server_key, _ = load_test_certs root_cert, _, _ = load_test_certs
blk = Proc.new { Creds.new(root_cert, _, cert_chain) } blk = proc { Creds.new(root_cert, nil, cert_chain) }
expect(&blk).to raise_error expect(&blk).to raise_error
end end
it 'can be constructed without a root_cret' do it 'can be constructed without a root_cret' do
_, server_key, cert_chain = load_test_certs _, server_key, cert_chain = load_test_certs
blk = Proc.new { Creds.new(_, server_key, cert_chain) } blk = proc { Creds.new(nil, server_key, cert_chain) }
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
end end
end end

@ -39,7 +39,6 @@ end
Server = GRPC::Core::Server Server = GRPC::Core::Server
describe Server do describe Server do
def create_test_cert def create_test_cert
GRPC::Core::ServerCredentials.new(*load_test_certs) GRPC::Core::ServerCredentials.new(*load_test_certs)
end end
@ -49,11 +48,8 @@ describe Server do
end end
describe '#start' do describe '#start' do
it 'runs without failing' do it 'runs without failing' do
blk = Proc.new do blk = proc { Server.new(@cq, nil).start }
s = Server.new(@cq, nil).start
end
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
@ -62,20 +58,19 @@ describe Server do
s.close s.close
expect { s.start }.to raise_error(RuntimeError) expect { s.start }.to raise_error(RuntimeError)
end end
end end
describe '#destroy' do describe '#destroy' do
it 'destroys a server ok' do it 'destroys a server ok' do
s = start_a_server s = start_a_server
blk = Proc.new { s.destroy } blk = proc { s.destroy }
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
it 'can be called more than once without error' do it 'can be called more than once without error' do
s = start_a_server s = start_a_server
begin begin
blk = Proc.new { s.destroy } blk = proc { s.destroy }
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
blk.call blk.call
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -89,7 +84,7 @@ describe Server do
it 'closes a server ok' do it 'closes a server ok' do
s = start_a_server s = start_a_server
begin begin
blk = Proc.new { s.close } blk = proc { s.close }
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
ensure ensure
s.close s.close
@ -98,7 +93,7 @@ describe Server do
it 'can be called more than once without error' do it 'can be called more than once without error' do
s = start_a_server s = start_a_server
blk = Proc.new { s.close } blk = proc { s.close }
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
blk.call blk.call
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
@ -106,11 +101,9 @@ describe Server do
end end
describe '#add_http_port' do describe '#add_http_port' do
describe 'for insecure servers' do describe 'for insecure servers' do
it 'runs without failing' do it 'runs without failing' do
blk = Proc.new do blk = proc do
s = Server.new(@cq, nil) s = Server.new(@cq, nil)
s.add_http2_port('localhost:0') s.add_http2_port('localhost:0')
s.close s.close
@ -123,13 +116,11 @@ describe Server do
s.close s.close
expect { s.add_http2_port('localhost:0') }.to raise_error(RuntimeError) expect { s.add_http2_port('localhost:0') }.to raise_error(RuntimeError)
end end
end end
describe 'for secure servers' do describe 'for secure servers' do
it 'runs without failing' do it 'runs without failing' do
blk = Proc.new do blk = proc do
s = Server.new(@cq, nil) s = Server.new(@cq, nil)
s.add_http2_port('localhost:0', true) s.add_http2_port('localhost:0', true)
s.close s.close
@ -140,16 +131,13 @@ describe Server do
it 'fails if the server is closed' do it 'fails if the server is closed' do
s = Server.new(@cq, nil) s = Server.new(@cq, nil)
s.close s.close
blk = Proc.new { s.add_http2_port('localhost:0', true) } blk = proc { s.add_http2_port('localhost:0', true) }
expect(&blk).to raise_error(RuntimeError) expect(&blk).to raise_error(RuntimeError)
end end
end end
end end
shared_examples '#new' do shared_examples '#new' do
it 'takes a completion queue with nil channel args' do it 'takes a completion queue with nil channel args' do
expect { Server.new(@cq, nil, create_test_cert) }.to_not raise_error expect { Server.new(@cq, nil, create_test_cert) }.to_not raise_error
end end
@ -162,14 +150,14 @@ describe Server do
end end
it 'does not take a hash with bad values as channel args' do it 'does not take a hash with bad values as channel args' do
blk = construct_with_args(:symbol => Object.new) blk = construct_with_args(symbol: Object.new)
expect(&blk).to raise_error TypeError expect(&blk).to raise_error TypeError
blk = construct_with_args('1' => Hash.new) blk = construct_with_args('1' => Hash.new)
expect(&blk).to raise_error TypeError expect(&blk).to raise_error TypeError
end end
it 'can take a hash with a symbol key as channel args' do it 'can take a hash with a symbol key as channel args' do
blk = construct_with_args(:a_symbol => 1) blk = construct_with_args(a_symbol: 1)
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
@ -179,17 +167,17 @@ describe Server do
end end
it 'can take a hash with a string value as channel args' do it 'can take a hash with a string value as channel args' do
blk = construct_with_args(:a_symbol => '1') blk = construct_with_args(a_symbol: '1')
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
it 'can take a hash with a symbol value as channel args' do it 'can take a hash with a symbol value as channel args' do
blk = construct_with_args(:a_symbol => :another_symbol) blk = construct_with_args(a_symbol: :another_symbol)
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
it 'can take a hash with a numeric value as channel args' do it 'can take a hash with a numeric value as channel args' do
blk = construct_with_args(:a_symbol => 1) blk = construct_with_args(a_symbol: 1)
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
@ -198,27 +186,22 @@ describe Server do
blk = construct_with_args(args) blk = construct_with_args(args)
expect(&blk).to_not raise_error expect(&blk).to_not raise_error
end end
end end
describe '#new with an insecure channel' do describe '#new with an insecure channel' do
def construct_with_args(a) def construct_with_args(a)
Proc.new { Server.new(@cq, a) } proc { Server.new(@cq, a) }
end end
it_behaves_like '#new' it_behaves_like '#new'
end end
describe '#new with a secure channel' do describe '#new with a secure channel' do
def construct_with_args(a) def construct_with_args(a)
Proc.new { Server.new(@cq, a, create_test_cert) } proc { Server.new(@cq, a, create_test_cert) }
end end
it_behaves_like '#new' it_behaves_like '#new'
end end
def start_a_server def start_a_server
@ -229,5 +212,4 @@ describe Server do
s.start s.start
s s
end end
end end

@ -32,7 +32,6 @@ require 'grpc'
TimeConsts = GRPC::Core::TimeConsts TimeConsts = GRPC::Core::TimeConsts
describe TimeConsts do describe TimeConsts do
before(:each) do before(:each) do
@known_consts = [:ZERO, :INFINITE_FUTURE, :INFINITE_PAST].sort @known_consts = [:ZERO, :INFINITE_FUTURE, :INFINITE_PAST].sort
end end
@ -49,11 +48,9 @@ describe TimeConsts do
end end
end end
end end
end end
describe '#from_relative_time' do describe '#from_relative_time' do
it 'cannot handle arbitrary objects' do it 'cannot handle arbitrary objects' do
expect { TimeConsts.from_relative_time(Object.new) }.to raise_error expect { TimeConsts.from_relative_time(Object.new) }.to raise_error
end end
@ -89,5 +86,4 @@ describe '#from_relative_time' do
expect(abs.to_f).to be_within(epsilon).of(want.to_f) expect(abs.to_f).to be_within(epsilon).of(want.to_f)
end end
end end
end end

@ -93,6 +93,7 @@ CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage
LDFLAGS_gcov = -fprofile-arcs -ftest-coverage LDFLAGS_gcov = -fprofile-arcs -ftest-coverage
DEFINES_gcov = NDEBUG DEFINES_gcov = NDEBUG
# General settings. # General settings.
# You may want to change these depending on your system. # You may want to change these depending on your system.
@ -113,6 +114,12 @@ ifndef VALID_CONFIG_$(CONFIG)
$(error Invalid CONFIG value '$(CONFIG)') $(error Invalid CONFIG value '$(CONFIG)')
endif endif
# The HOST compiler settings are used to compile the protoc plugins.
# In most cases, you won't have to change anything, but if you are
# cross-compiling, you can override these variables from GNU make's
# command line: make CC=cross-gcc HOST_CC=gcc
HOST_CC = $(CC) HOST_CC = $(CC)
HOST_CXX = $(CXX) HOST_CXX = $(CXX)
HOST_LD = $(LD) HOST_LD = $(LD)
@ -189,6 +196,13 @@ endif
OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS) OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS)
ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS) ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS)
PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/perftools.c -lprofiler $(LDFLAGS)
HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_SYSTEM_PERFTOOLS),true)
DEFINES += GRPC_HAVE_PERFTOOLS
LIBS += profiler
endif
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
@ -337,7 +351,7 @@ static: static_c static_cxx
static_c: \ static_c: \
% for lib in libs: % for lib in libs:
% if lib.build == 'all' and not lib.get('c++', False): % if lib.build == 'all' and lib.language == 'c':
libs/$(CONFIG)/lib${lib.name}.a\ libs/$(CONFIG)/lib${lib.name}.a\
% endif % endif
% endfor % endfor
@ -345,7 +359,7 @@ static_c: \
static_cxx: \ static_cxx: \
% for lib in libs: % for lib in libs:
% if lib.build == 'all' and lib.get('c++', False): % if lib.build == 'all' and lib.language == 'c++':
libs/$(CONFIG)/lib${lib.name}.a\ libs/$(CONFIG)/lib${lib.name}.a\
% endif % endif
% endfor % endfor
@ -355,7 +369,7 @@ shared: shared_c shared_cxx
shared_c: \ shared_c: \
% for lib in libs: % for lib in libs:
% if lib.build == 'all' and not lib.get('c++', False): % if lib.build == 'all' and lib.language == 'c':
libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\ libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
% endif % endif
% endfor % endfor
@ -363,7 +377,7 @@ shared_c: \
shared_cxx: \ shared_cxx: \
% for lib in libs: % for lib in libs:
% if lib.build == 'all' and lib.get('c++', False): % if lib.build == 'all' and lib.language == 'c++':
libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\ libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)\
% endif % endif
% endfor % endfor
@ -373,7 +387,7 @@ privatelibs: privatelibs_c privatelibs_cxx
privatelibs_c: \ privatelibs_c: \
% for lib in libs: % for lib in libs:
% if lib.build == 'private' and not lib.get('c++', False): % if lib.build == 'private' and lib.language == 'c':
libs/$(CONFIG)/lib${lib.name}.a\ libs/$(CONFIG)/lib${lib.name}.a\
% endif % endif
% endfor % endfor
@ -381,7 +395,7 @@ privatelibs_c: \
privatelibs_cxx: \ privatelibs_cxx: \
% for lib in libs: % for lib in libs:
% if lib.build == 'private' and lib.get('c++', False): % if lib.build == 'private' and lib.language == 'c++':
libs/$(CONFIG)/lib${lib.name}.a\ libs/$(CONFIG)/lib${lib.name}.a\
% endif % endif
% endfor % endfor
@ -391,7 +405,7 @@ buildtests: buildtests_c buildtests_cxx
buildtests_c: privatelibs_c\ buildtests_c: privatelibs_c\
% for tgt in targets: % for tgt in targets:
% if tgt.build == 'test' and not tgt.get('c++', False): % if tgt.build == 'test' and not tgt.language == 'c++':
bins/$(CONFIG)/${tgt.name}\ bins/$(CONFIG)/${tgt.name}\
% endif % endif
% endfor % endfor
@ -399,7 +413,7 @@ buildtests_c: privatelibs_c\
buildtests_cxx: privatelibs_cxx\ buildtests_cxx: privatelibs_cxx\
% for tgt in targets: % for tgt in targets:
% if tgt.build == 'test' and tgt.get('c++', False): % if tgt.build == 'test' and tgt.language == 'c++':
bins/$(CONFIG)/${tgt.name}\ bins/$(CONFIG)/${tgt.name}\
% endif % endif
% endfor % endfor
@ -409,7 +423,7 @@ test: test_c test_cxx
test_c: buildtests_c test_c: buildtests_c
% for tgt in targets: % for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and not tgt.get('c++', False): % if tgt.build == 'test' and tgt.get('run', True) and not tgt.language == 'c++':
$(E) "[RUN] Testing ${tgt.name}" $(E) "[RUN] Testing ${tgt.name}"
$(Q) ./bins/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 ) $(Q) ./bins/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif % endif
@ -418,7 +432,7 @@ test_c: buildtests_c
test_cxx: buildtests_cxx test_cxx: buildtests_cxx
% for tgt in targets: % for tgt in targets:
% if tgt.build == 'test' and tgt.get('run', True) and tgt.get('c++', False): % if tgt.build == 'test' and tgt.get('run', True) and tgt.language == 'c++':
$(E) "[RUN] Testing ${tgt.name}" $(E) "[RUN] Testing ${tgt.name}"
$(Q) ./bins/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 ) $(Q) ./bins/$(CONFIG)/${tgt.name} || ( echo test ${tgt.name} failed ; exit 1 )
% endif % endif
@ -449,9 +463,14 @@ strip-static: strip-static_c strip-static_cxx
strip-shared: strip-shared_c strip-shared_cxx strip-shared: strip-shared_c strip-shared_cxx
# TODO(nnoble): the strip target is stripping in-place, instead
# of copying files in a temporary folder.
# This prevents proper debugging after running make install.
strip-static_c: static_c strip-static_c: static_c
% for lib in libs: % for lib in libs:
% if not lib.get("c++", False): % if lib.language == "c":
% if lib.build == "all": % if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.a" $(E) "[STRIP] Stripping lib${lib.name}.a"
$(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.a $(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.a
@ -461,7 +480,7 @@ strip-static_c: static_c
strip-static_cxx: static_cxx strip-static_cxx: static_cxx
% for lib in libs: % for lib in libs:
% if lib.get("c++", False): % if lib.language == "c++":
% if lib.build == "all": % if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.a" $(E) "[STRIP] Stripping lib${lib.name}.a"
$(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.a $(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.a
@ -471,7 +490,7 @@ strip-static_cxx: static_cxx
strip-shared_c: shared_c strip-shared_c: shared_c
% for lib in libs: % for lib in libs:
% if not lib.get("c++", False): % if lib.language == "c":
% if lib.build == "all": % if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.so" $(E) "[STRIP] Stripping lib${lib.name}.so"
$(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)
@ -481,7 +500,7 @@ strip-shared_c: shared_c
strip-shared_cxx: shared_cxx strip-shared_cxx: shared_cxx
% for lib in libs: % for lib in libs:
% if lib.get("c++", False): % if lib.language == "c++":
% if lib.build == "all": % if lib.build == "all":
$(E) "[STRIP] Stripping lib${lib.name}.so" $(E) "[STRIP] Stripping lib${lib.name}.so"
$(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(Q) $(STRIP) libs/$(CONFIG)/lib${lib.name}.$(SHARED_EXT)
@ -538,7 +557,7 @@ install-static: install-static_c install-static_cxx
install-static_c: static_c strip-static_c install-static_c: static_c strip-static_c
% for lib in libs: % for lib in libs:
% if not lib.get("c++", False): % if lib.language == "c":
% if lib.build == "all": % if lib.build == "all":
$(E) "[INSTALL] Installing lib${lib.name}.a" $(E) "[INSTALL] Installing lib${lib.name}.a"
$(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a $(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
@ -548,7 +567,7 @@ install-static_c: static_c strip-static_c
install-static_cxx: static_cxx strip-static_cxx install-static_cxx: static_cxx strip-static_cxx
% for lib in libs: % for lib in libs:
% if lib.get("c++", False): % if lib.language == "c++":
% if lib.build == "all": % if lib.build == "all":
$(E) "[INSTALL] Installing lib${lib.name}.a" $(E) "[INSTALL] Installing lib${lib.name}.a"
$(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a $(Q) $(INSTALL) libs/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a
@ -558,7 +577,7 @@ install-static_cxx: static_cxx strip-static_cxx
install-shared_c: shared_c strip-shared_c install-shared_c: shared_c strip-shared_c
% for lib in libs: % for lib in libs:
% if not lib.get("c++", False): % if lib.language == "c":
% if lib.build == "all": % if lib.build == "all":
ifeq ($(SYSTEM),MINGW32) ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)" $(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)"
@ -582,7 +601,7 @@ endif
install-shared_cxx: shared_cxx strip-shared_cxx install-shared_cxx: shared_cxx strip-shared_cxx
% for lib in libs: % for lib in libs:
% if lib.get("c++", False): % if lib.language == "c++":
% if lib.build == "all": % if lib.build == "all":
ifeq ($(SYSTEM),MINGW32) ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)" $(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)"
@ -630,7 +649,7 @@ LIB${lib.name.upper()}_SRC = \\
% endfor % endfor
% if "public_headers" in lib: % if "public_headers" in lib:
% if lib.get("c++", False): % if lib.language == "c++":
PUBLIC_HEADERS_CXX += \\ PUBLIC_HEADERS_CXX += \\
% else: % else:
@ -645,9 +664,12 @@ PUBLIC_HEADERS_C += \\
LIB${lib.name.upper()}_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(LIB${lib.name.upper()}_SRC)))) LIB${lib.name.upper()}_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(LIB${lib.name.upper()}_SRC))))
## If the library requires OpenSSL with ALPN, let's add some restrictions.
% if lib.get('secure', True): % if lib.get('secure', True):
ifeq ($(NO_SECURE),true) ifeq ($(NO_SECURE),true)
# You can't build secure libraries if you don't have OpenSSL with ALPN.
libs/$(CONFIG)/lib${lib.name}.a: openssl_dep_error libs/$(CONFIG)/lib${lib.name}.a: openssl_dep_error
% if lib.build == "all": % if lib.build == "all":
@ -667,6 +689,7 @@ ${src}: $(OPENSSL_DEP)
endif endif
libs/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(LIB${lib.name.upper()}_OBJS) libs/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(LIB${lib.name.upper()}_OBJS)
## The else here corresponds to the if secure earlier.
% else: % else:
libs/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP) $(LIB${lib.name.upper()}_OBJS) libs/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP) $(LIB${lib.name.upper()}_OBJS)
% endif % endif
@ -686,7 +709,7 @@ libs/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP) $(LIB${lib.name.upper()}_OBJS)
% endif % endif
<% <%
if lib.get('c++', False): if lib.language == 'c++':
ld = '$(LDXX)' ld = '$(LDXX)'
else: else:
ld = '$(LD)' ld = '$(LD)'
@ -731,6 +754,8 @@ endif
endif endif
% endif % endif
## If the lib was secure, we have to close the Makefile's if that tested
## the presence of an ALPN-capable OpenSSL.
% if lib.get('secure', True): % if lib.get('secure', True):
endif endif
@ -772,17 +797,29 @@ ${tgt.name.upper()}_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basena
% if tgt.get('secure', True): % if tgt.get('secure', True):
ifeq ($(NO_SECURE),true) ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL with ALPN.
bins/$(CONFIG)/${tgt.name}: openssl_dep_error bins/$(CONFIG)/${tgt.name}: openssl_dep_error
else else
% endif % endif
##
## We're not trying to add a dependency on building zlib and openssl here,
## as it's already done in the libraries. We're assuming that the build
## trickles down, and that a secure target requires a secure version of
## a library.
##
## That simplifies the codegen a bit, but prevents a fully defined Makefile.
## I can live with that.
##
bins/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\ bins/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\
% for dep in tgt.deps: % for dep in tgt.deps:
libs/$(CONFIG)/lib${dep}.a\ libs/$(CONFIG)/lib${dep}.a\
% endfor % endfor
% if tgt.get("c++", False): % if tgt.language == "c++":
## C++ targets specificies.
% if tgt.build == 'protoc': % if tgt.build == 'protoc':
$(E) "[HOSTLD] Linking $@" $(E) "[HOSTLD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
@ -796,6 +833,7 @@ bins/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\
$(GTEST_LIB)\ $(GTEST_LIB)\
% endif % endif
% else: % else:
## C-only targets specificities.
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(${tgt.name.upper()}_OBJS)\ $(Q) $(LD) $(LDFLAGS) $(${tgt.name.upper()}_OBJS)\
@ -803,7 +841,7 @@ bins/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\
% for dep in tgt.deps: % for dep in tgt.deps:
libs/$(CONFIG)/lib${dep}.a\ libs/$(CONFIG)/lib${dep}.a\
% endfor % endfor
% if tgt.get("c++", False): % if tgt.language == "c++":
% if tgt.build == 'protoc': % if tgt.build == 'protoc':
$(HOST_LDLIBSXX)\ $(HOST_LDLIBSXX)\
% else: % else:

@ -0,0 +1,9 @@
<%!
import json
%>
${json.dumps([{"name": tgt.name, "language": tgt.language}
for tgt in targets
if tgt.build == "test" and tgt.name[-5:] == "_test"],
sort_keys=True, indent=2)}

@ -23,7 +23,7 @@ projects.extend(targets)
projects = [project for project in projects if project.get('vs_project_guid', None)] projects = [project for project in projects if project.get('vs_project_guid', None)]
## Exclude C++ projects for now ## Exclude C++ projects for now
projects = [project for project in projects if not project.get('c++', False)] projects = [project for project in projects if not project.language == 'c++']
for p in projects: for p in projects:
p.deps = p.get('deps',[]) p.deps = p.get('deps',[])

@ -0,0 +1,7 @@
#include <gperftools/profiler.h>
int main() {
ProfilerStart("/dev/null");
ProfilerStop();
return 0;
}

@ -223,6 +223,8 @@ static void verify_matches(expectation *e, grpc_event *ev) {
GPR_ASSERT(ev->data.read == NULL); GPR_ASSERT(ev->data.read == NULL);
} }
break; break;
case GRPC_SERVER_SHUTDOWN:
break;
case GRPC_COMPLETION_DO_NOT_USE: case GRPC_COMPLETION_DO_NOT_USE:
gpr_log(GPR_ERROR, "not implemented"); gpr_log(GPR_ERROR, "not implemented");
abort(); abort();
@ -295,6 +297,8 @@ static size_t expectation_to_string(char *out, expectation *e) {
len = sprintf(out, "GRPC_READ data=%s", str); len = sprintf(out, "GRPC_READ data=%s", str);
gpr_free(str); gpr_free(str);
return len; return len;
case GRPC_SERVER_SHUTDOWN:
return sprintf(out, "GRPC_SERVER_SHUTDOWN");
case GRPC_COMPLETION_DO_NOT_USE: case GRPC_COMPLETION_DO_NOT_USE:
case GRPC_QUEUE_SHUTDOWN: case GRPC_QUEUE_SHUTDOWN:
gpr_log(GPR_ERROR, "not implemented"); gpr_log(GPR_ERROR, "not implemented");
@ -487,3 +491,7 @@ void cq_expect_finished(cq_verifier *v, void *tag, ...) {
finished_internal(v, tag, GRPC_STATUS__DO_NOT_USE, NULL, args); finished_internal(v, tag, GRPC_STATUS__DO_NOT_USE, NULL, args);
va_end(args); va_end(args);
} }
void cq_expect_server_shutdown(cq_verifier *v, void *tag) {
add(v, GRPC_SERVER_SHUTDOWN, tag);
}

@ -70,5 +70,6 @@ void cq_expect_finished_with_status(cq_verifier *v, void *tag,
grpc_status_code status_code, grpc_status_code status_code,
const char *details, ...); const char *details, ...);
void cq_expect_finished(cq_verifier *v, void *tag, ...); void cq_expect_finished(cq_verifier *v, void *tag, ...);
void cq_expect_server_shutdown(cq_verifier *v, void *tag);
#endif /* __GRPC_TEST_END2END_CQ_VERIFIER_H__ */ #endif /* __GRPC_TEST_END2END_CQ_VERIFIER_H__ */

@ -25,6 +25,7 @@ END2END_TESTS = [
'disappearing_server', 'disappearing_server',
'early_server_shutdown_finishes_inflight_calls', 'early_server_shutdown_finishes_inflight_calls',
'early_server_shutdown_finishes_tags', 'early_server_shutdown_finishes_tags',
'graceful_server_shutdown',
'invoke_large_request', 'invoke_large_request',
'max_concurrent_streams', 'max_concurrent_streams',
'no_op', 'no_op',
@ -47,6 +48,7 @@ def main():
{ {
'name': 'end2end_fixture_%s' % f, 'name': 'end2end_fixture_%s' % f,
'build': 'private', 'build': 'private',
'language': 'c',
'secure': True, 'secure': True,
'src': ['test/core/end2end/fixtures/%s.c' % f] 'src': ['test/core/end2end/fixtures/%s.c' % f]
} }
@ -54,6 +56,7 @@ def main():
{ {
'name': 'end2end_test_%s' % t, 'name': 'end2end_test_%s' % t,
'build': 'private', 'build': 'private',
'language': 'c',
'secure': False, 'secure': False,
'src': ['test/core/end2end/tests/%s.c' % t], 'src': ['test/core/end2end/tests/%s.c' % t],
'headers': ['test/core/end2end/tests/cancel_test_helpers.h'] 'headers': ['test/core/end2end/tests/cancel_test_helpers.h']
@ -62,6 +65,7 @@ def main():
{ {
'name': 'end2end_certs', 'name': 'end2end_certs',
'build': 'private', 'build': 'private',
'language': 'c',
'src': [ 'src': [
"test/core/end2end/data/test_root_cert.c", "test/core/end2end/data/test_root_cert.c",
"test/core/end2end/data/prod_roots_certs.c", "test/core/end2end/data/prod_roots_certs.c",
@ -74,6 +78,7 @@ def main():
{ {
'name': '%s_%s_test' % (f, t), 'name': '%s_%s_test' % (f, t),
'build': 'test', 'build': 'test',
'language': 'c',
'src': [], 'src': [],
'deps': [ 'deps': [
'end2end_fixture_%s' % f, 'end2end_fixture_%s' % f,

@ -0,0 +1,160 @@
/*
*
* Copyright 2014, 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.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "test/core/end2end/cq_verifier.h"
enum { TIMEOUT = 200000 };
static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
return f;
}
static gpr_timespec n_seconds_time(int n) {
return gpr_time_add(gpr_now(), gpr_time_from_micros(GPR_US_PER_SEC * n));
}
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
static void drain_cq(grpc_completion_queue *cq) {
grpc_event *ev;
grpc_completion_type type;
do {
ev = grpc_completion_queue_next(cq, five_seconds_time());
GPR_ASSERT(ev);
type = ev->type;
grpc_event_finish(ev);
} while (type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->server_cq);
drain_cq(f->server_cq);
grpc_completion_queue_destroy(f->server_cq);
grpc_completion_queue_shutdown(f->client_cq);
drain_cq(f->client_cq);
grpc_completion_queue_destroy(f->client_cq);
}
static void test_early_server_shutdown_finishes_inflight_calls(
grpc_end2end_test_config config) {
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
grpc_call *c;
grpc_call *s;
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline);
GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_start_invoke(c, f.client_cq, tag(1), tag(2), tag(3), 0));
cq_expect_invoke_accepted(v_client, tag(1), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4)));
cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com",
deadline, NULL);
cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102)));
GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0));
cq_expect_client_metadata_read(v_client, tag(2), NULL);
cq_verify(v_client);
/* shutdown the server */
grpc_server_shutdown_and_notify(f.server, tag(0xdead));
cq_verify_empty(v_server);
grpc_call_start_write_status(s, GRPC_STATUS_OK, NULL, tag(103));
grpc_call_destroy(s);
cq_expect_finish_accepted(v_server, tag(103), GRPC_OP_OK);
cq_expect_finished(v_server, tag(102), NULL);
cq_expect_server_shutdown(v_server, tag(0xdead));
cq_verify(v_server);
cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_OK, NULL, NULL);
cq_verify(v_client);
grpc_call_destroy(c);
cq_verifier_destroy(v_client);
cq_verifier_destroy(v_server);
end_test(&f);
config.tear_down_data(&f);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
test_early_server_shutdown_finishes_inflight_calls(config);
}

@ -32,6 +32,7 @@
*/ */
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
@ -47,6 +48,7 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "test/core/util/port.h" #include "test/core/util/port.h"
#include "test/core/end2end/data/ssl_test_data.h"
static grpc_completion_queue *cq; static grpc_completion_queue *cq;
static grpc_server *server; static grpc_server *server;
@ -98,8 +100,17 @@ int main(int argc, char **argv) {
gpr_log(GPR_INFO, "creating server on: %s", addr); gpr_log(GPR_INFO, "creating server on: %s", addr);
cq = grpc_completion_queue_create(); cq = grpc_completion_queue_create();
if (secure) {
grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(
NULL, 0, test_server1_key, test_server1_key_size, test_server1_cert,
test_server1_cert_size);
server = grpc_secure_server_create(ssl_creds, cq, NULL);
GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr));
grpc_server_credentials_release(ssl_creds);
} else {
server = grpc_server_create(cq, NULL); server = grpc_server_create(cq, NULL);
GPR_ASSERT(grpc_server_add_http2_port(server, addr)); GPR_ASSERT(grpc_server_add_http2_port(server, addr));
}
grpc_server_start(server); grpc_server_start(server);
gpr_free(addr_buf); gpr_free(addr_buf);

@ -0,0 +1,101 @@
/*
*
* 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.
*
*/
#include "src/core/iomgr/pollset_kick.h"
#include <grpc/support/log.h>
#include "test/core/util/test_config.h"
static void test_allocation() {
grpc_pollset_kick_state state;
grpc_pollset_kick_init(&state);
grpc_pollset_kick_destroy(&state);
}
static void test_non_kick() {
grpc_pollset_kick_state state;
int fd;
grpc_pollset_kick_init(&state);
fd = grpc_pollset_kick_pre_poll(&state);
GPR_ASSERT(fd >= 0);
grpc_pollset_kick_post_poll(&state);
grpc_pollset_kick_destroy(&state);
}
static void test_basic_kick() {
/* Kicked during poll */
grpc_pollset_kick_state state;
int fd;
grpc_pollset_kick_init(&state);
fd = grpc_pollset_kick_pre_poll(&state);
GPR_ASSERT(fd >= 0);
grpc_pollset_kick_kick(&state);
/* Now hypothetically we polled and found that we were kicked */
grpc_pollset_kick_consume(&state);
grpc_pollset_kick_post_poll(&state);
grpc_pollset_kick_destroy(&state);
}
static void test_non_poll_kick() {
/* Kick before entering poll */
grpc_pollset_kick_state state;
int fd;
grpc_pollset_kick_init(&state);
grpc_pollset_kick_kick(&state);
fd = grpc_pollset_kick_pre_poll(&state);
GPR_ASSERT(fd < 0);
grpc_pollset_kick_destroy(&state);
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_pollset_kick_global_init();
test_allocation();
test_basic_kick();
test_non_poll_kick();
test_non_kick();
grpc_pollset_kick_global_destroy();
return 0;
}

@ -64,8 +64,8 @@ static void free_data(void* data) { gpr_free(data); }
static void test_create_table(void) { static void test_create_table(void) {
/* Create table with uint64 key type */ /* Create table with uint64 key type */
census_ht* ht = NULL; census_ht* ht = NULL;
census_ht_option ht_options = {CENSUS_HT_UINT64, 1999, NULL, NULL, NULL, census_ht_option ht_options = {CENSUS_HT_UINT64, 1999, NULL,
NULL}; NULL, NULL, NULL};
ht = census_ht_create(&ht_options); ht = census_ht_create(&ht_options);
GPR_ASSERT(ht != NULL); GPR_ASSERT(ht != NULL);
GPR_ASSERT(census_ht_get_size(ht) == 0); GPR_ASSERT(census_ht_get_size(ht) == 0);
@ -119,8 +119,8 @@ static void test_table_with_int_key(void) {
/* Test that there is no memory leak when keys and values are owned by table. */ /* Test that there is no memory leak when keys and values are owned by table. */
static void test_value_and_key_deleter(void) { static void test_value_and_key_deleter(void) {
census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, &cmp_str_keys, census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64,
&free_data, &free_data}; &cmp_str_keys, &free_data, &free_data};
census_ht* ht = census_ht_create(&opt); census_ht* ht = census_ht_create(&opt);
census_ht_key key; census_ht_key key;
char* val = NULL; char* val = NULL;
@ -208,12 +208,12 @@ static void test_insertion_and_deletion_with_high_collision_rate(void) {
} }
static void test_table_with_string_key(void) { static void test_table_with_string_key(void) {
census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, &cmp_str_keys, NULL, census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64,
NULL}; &cmp_str_keys, NULL, NULL};
census_ht* ht = census_ht_create(&opt); census_ht* ht = census_ht_create(&opt);
const char* keys[] = {"k1", "a", "000", "apple", const char* keys[] = {"k1", "a", "000",
"banana_a_long_long_long_banana", "%$", "111", "foo", "apple", "banana_a_long_long_long_banana", "%$",
"b"}; "111", "foo", "b"};
const int vals[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; const int vals[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int i = 0; int i = 0;
GPR_ASSERT(ht != NULL); GPR_ASSERT(ht != NULL);

@ -58,8 +58,8 @@ static void producer_thread(void *arg) {
for (i = 0; i < opt->iterations; i++) { for (i = 0; i < opt->iterations; i++) {
grpc_cq_begin_op(opt->cc, NULL, GRPC_WRITE_ACCEPTED); grpc_cq_begin_op(opt->cc, NULL, GRPC_WRITE_ACCEPTED);
grpc_cq_end_write_accepted(opt->cc, (void *)(gpr_intptr)1, NULL, NULL, NULL, grpc_cq_end_write_accepted(opt->cc, (void *)(gpr_intptr) 1, NULL, NULL,
GRPC_OP_OK); NULL, GRPC_OP_OK);
} }
gpr_event_set(&opt->on_finished, (void *)(gpr_intptr) 1); gpr_event_set(&opt->on_finished, (void *)(gpr_intptr) 1);

@ -296,8 +296,8 @@ static void producer_thread(void *arg) {
gpr_log(GPR_INFO, "producer %d phase 2", opt->id); gpr_log(GPR_INFO, "producer %d phase 2", opt->id);
for (i = 0; i < TEST_THREAD_EVENTS; i++) { for (i = 0; i < TEST_THREAD_EVENTS; i++) {
grpc_cq_end_write_accepted(opt->cc, (void *)(gpr_intptr)1, NULL, NULL, NULL, grpc_cq_end_write_accepted(opt->cc, (void *)(gpr_intptr) 1, NULL, NULL,
GRPC_OP_OK); NULL, GRPC_OP_OK);
opt->events_triggered++; opt->events_triggered++;
} }

@ -33,6 +33,22 @@
#include "test/core/util/grpc_profiler.h" #include "test/core/util/grpc_profiler.h"
void grpc_profiler_start(const char *filename) {} #if GRPC_HAVE_PERFTOOLS
#include <gperftools/profiler.h>
void grpc_profiler_start(const char *filename) { ProfilerStart(filename); }
void grpc_profiler_stop() { ProfilerStop(); }
#else
#include <grpc/support/log.h>
void grpc_profiler_start(const char *filename) {
gpr_log(GPR_DEBUG,
"You do not have google-perftools installed, profiling is disabled");
gpr_log(GPR_DEBUG,
"To install on ubuntu: sudo apt-get install google-perftools "
"libgoogle-perftools-dev");
}
void grpc_profiler_stop(void) {} void grpc_profiler_stop(void) {}
#endif

@ -0,0 +1,63 @@
#!/usr/bin/python
# produces cleaner build.json files
import collections
import json
import os
import sys
TEST = (os.environ.get('TEST', 'false') == 'true')
_TOP_LEVEL_KEYS = ['settings', 'filegroups', 'libs', 'targets']
_VERSION_KEYS = ['major', 'minor', 'micro', 'build']
_ELEM_KEYS = [
'name',
'build',
'language',
'public_headers',
'headers',
'src',
'deps']
def rebuild_as_ordered_dict(indict, special_keys):
outdict = collections.OrderedDict()
for key in special_keys:
if key in indict:
outdict[key] = indict[key]
for key in sorted(indict.keys()):
if key in special_keys: continue
outdict[key] = indict[key]
return outdict
def clean_elem(indict):
for name in ['public_headers', 'headers', 'src']:
if name not in indict: continue
inlist = indict[name]
protos = set(x for x in inlist if os.path.splitext(x)[1] == '.proto')
others = set(x for x in inlist if x not in protos)
indict[name] = sorted(protos) + sorted(others)
return rebuild_as_ordered_dict(indict, _ELEM_KEYS)
for filename in sys.argv[1:]:
with open(filename) as f:
js = json.load(f)
js = rebuild_as_ordered_dict(js, _TOP_LEVEL_KEYS)
js['settings']['version'] = rebuild_as_ordered_dict(
js['settings']['version'], _VERSION_KEYS)
for grp in ['filegroups', 'libs', 'targets']:
if grp not in js: continue
js[grp] = sorted([clean_elem(x) for x in js[grp]],
key=lambda x: (x.get('language', '_'), x['name']))
output = json.dumps(js, indent = 2)
# massage out trailing whitespace
lines = []
for line in output.splitlines():
lines.append(line.rstrip() + '\n')
output = ''.join(lines)
if TEST:
with open(filename) as f:
assert f.read() == output
else:
with open(filename, 'w') as f:
f.write(output)

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
set -x set -e
if [ "x$TEST" == "x" ] ; then if [ "x$TEST" == "x" ] ; then
TEST=false TEST=false
@ -32,7 +32,7 @@ for dir in . ; do
data=`for i in $json_files; do echo -n "-d $i "; done` data=`for i in $json_files; do echo -n "-d $i "; done`
if [ $TEST == true ] ; then if [ $TEST == true ] ; then
actual_out=$out actual_out=$out
out=`mktemp` out=`mktemp /tmp/gentXXXXXX`
fi fi
$mako_renderer $plugins $data -o $out $file $mako_renderer $plugins $data -o $out $file
if [ $TEST == true ] ; then if [ $TEST == true ] ; then

@ -1,8 +1,9 @@
#!/bin/bash #!/bin/bash
set -ex set -e
source $(dirname $0)/config.sh
cd $(dirname $0)/../.. cd $(dirname $0)/../..
for dir in src test include for dir in src test include
do do
find $dir -name '*.c' -or -name '*.cc' -or -name '*.h' | xargs clang-format -i find $dir -name '*.c' -or -name '*.cc' -or -name '*.h' | xargs $CLANG_FORMAT -i
done done

@ -0,0 +1,11 @@
CLANG_FORMAT=clang-format-3.5
set -ex
if not hash $CLANG_FORMAT 2>/dev/null; then
echo "$CLANG_FORMAT is needed but not installed"
echo "perhaps try:"
echo " sudo apt-get install $CLANG_FORMAT"
exit 1
fi

@ -0,0 +1,21 @@
#!/bin/bash
set -ex
# change to grpc repo root
cd $(dirname $0)/../..
root=`pwd`
export GRPC_LIB_SUBDIR=libs/opt
# make the libraries
make -j static_c
# build php
cd src/php
cd ext/grpc
phpize
./configure --enable-grpc=$root
make

@ -4,13 +4,13 @@
import argparse import argparse
import glob import glob
import itertools import itertools
import json
import multiprocessing import multiprocessing
import os import os
import sys import sys
import time import time
import jobset import jobset
import simplejson
import watch_dirs import watch_dirs
@ -20,6 +20,7 @@ class SimpleConfig(object):
def __init__(self, config): def __init__(self, config):
self.build_config = config self.build_config = config
self.maxjobs = 32 * multiprocessing.cpu_count() self.maxjobs = 32 * multiprocessing.cpu_count()
self.allow_hashing = (config != 'gcov')
def run_command(self, binary): def run_command(self, binary):
return [binary] return [binary]
@ -32,11 +33,48 @@ class ValgrindConfig(object):
self.build_config = config self.build_config = config
self.tool = tool self.tool = tool
self.maxjobs = 4 * multiprocessing.cpu_count() self.maxjobs = 4 * multiprocessing.cpu_count()
self.allow_hashing = False
def run_command(self, binary): def run_command(self, binary):
return ['valgrind', binary, '--tool=%s' % self.tool] return ['valgrind', binary, '--tool=%s' % self.tool]
class CLanguage(object):
def __init__(self, make_target, test_lang):
self.allow_hashing = True
self.make_target = make_target
with open('tools/run_tests/tests.json') as f:
js = json.load(f)
self.binaries = [tgt['name']
for tgt in js
if tgt['language'] == test_lang]
def test_binaries(self, config):
return ['bins/%s/%s' % (config, binary) for binary in self.binaries]
def make_targets(self):
return ['buildtests_%s' % self.make_target]
def build_steps(self):
return []
class PhpLanguage(object):
def __init__(self):
self.allow_hashing = False
def test_binaries(self, config):
return ['src/php/bin/run_tests.sh']
def make_targets(self):
return []
def build_steps(self):
return [['tools/run_tests/build_php.sh']]
# different configurations we can run under # different configurations we can run under
_CONFIGS = { _CONFIGS = {
'dbg': SimpleConfig('dbg'), 'dbg': SimpleConfig('dbg'),
@ -51,9 +89,10 @@ _CONFIGS = {
_DEFAULT = ['dbg', 'opt'] _DEFAULT = ['dbg', 'opt']
_LANGUAGE_TEST_TARGETS = { _LANGUAGES = {
'c++': 'buildtests_cxx', 'c++': CLanguage('cxx', 'c++'),
'c': 'buildtests_c', 'c': CLanguage('c', 'c'),
'php': PhpLanguage()
} }
# parse command line # parse command line
@ -62,7 +101,6 @@ argp.add_argument('-c', '--config',
choices=['all'] + sorted(_CONFIGS.keys()), choices=['all'] + sorted(_CONFIGS.keys()),
nargs='+', nargs='+',
default=_DEFAULT) default=_DEFAULT)
argp.add_argument('-t', '--test-filter', nargs='*', default=['*'])
argp.add_argument('-n', '--runs_per_test', default=1, type=int) argp.add_argument('-n', '--runs_per_test', default=1, type=int)
argp.add_argument('-f', '--forever', argp.add_argument('-f', '--forever',
default=False, default=False,
@ -73,9 +111,9 @@ argp.add_argument('--newline_on_success',
action='store_const', action='store_const',
const=True) const=True)
argp.add_argument('-l', '--language', argp.add_argument('-l', '--language',
choices=sorted(_LANGUAGE_TEST_TARGETS.keys()), choices=sorted(_LANGUAGES.keys()),
nargs='+', nargs='+',
default=sorted(_LANGUAGE_TEST_TARGETS.keys())) default=sorted(_LANGUAGES.keys()))
args = argp.parse_args() args = argp.parse_args()
# grab config # grab config
@ -84,8 +122,18 @@ run_configs = set(_CONFIGS[cfg]
_CONFIGS.iterkeys() if x == 'all' else [x] _CONFIGS.iterkeys() if x == 'all' else [x]
for x in args.config)) for x in args.config))
build_configs = set(cfg.build_config for cfg in run_configs) build_configs = set(cfg.build_config for cfg in run_configs)
make_targets = set(_LANGUAGE_TEST_TARGETS[x] for x in args.language)
filters = args.test_filter make_targets = []
languages = set(_LANGUAGES[l] for l in args.language)
build_steps = [['make',
'-j', '%d' % (multiprocessing.cpu_count() + 1),
'CONFIG=%s' % cfg] + list(set(
itertools.chain.from_iterable(l.make_targets()
for l in languages)))
for cfg in build_configs] + list(
itertools.chain.from_iterable(l.build_steps()
for l in languages))
runs_per_test = args.runs_per_test runs_per_test = args.runs_per_test
forever = args.forever forever = args.forever
@ -116,37 +164,30 @@ class TestCache(object):
def save(self): def save(self):
with open('.run_tests_cache', 'w') as f: with open('.run_tests_cache', 'w') as f:
f.write(simplejson.dumps(self.dump())) f.write(json.dumps(self.dump()))
def maybe_load(self): def maybe_load(self):
if os.path.exists('.run_tests_cache'): if os.path.exists('.run_tests_cache'):
with open('.run_tests_cache') as f: with open('.run_tests_cache') as f:
self.parse(simplejson.loads(f.read())) self.parse(json.loads(f.read()))
def _build_and_run(check_cancelled, newline_on_success, cache): def _build_and_run(check_cancelled, newline_on_success, cache):
"""Do one pass of building & running tests.""" """Do one pass of building & running tests."""
# build latest, sharing cpu between the various makes # build latest, sharing cpu between the various makes
if not jobset.run( if not jobset.run(build_steps):
(['make',
'-j', '%d' % (multiprocessing.cpu_count() + 1),
'CONFIG=%s' % cfg] + list(make_targets)
for cfg in build_configs),
check_cancelled, maxjobs=1):
return 1 return 1
# run all the tests # run all the tests
if not jobset.run( one_run = dict(
itertools.ifilter( (' '.join(config.run_command(x)), config.run_command(x))
lambda x: x is not None, (
config.run_command(x)
for config in run_configs for config in run_configs
for filt in filters for language in args.language
for x in itertools.chain.from_iterable(itertools.repeat( for x in _LANGUAGES[language].test_binaries(config.build_config)
glob.glob('bins/%s/%s_test' % ( ).values()
config.build_config, filt)), all_runs = itertools.chain.from_iterable(
runs_per_test)))), itertools.repeat(one_run, runs_per_test))
check_cancelled, if not jobset.run(all_runs, check_cancelled,
newline_on_success=newline_on_success, newline_on_success=newline_on_success,
maxjobs=min(c.maxjobs for c in run_configs), maxjobs=min(c.maxjobs for c in run_configs),
cache=cache): cache=cache):
@ -155,9 +196,9 @@ def _build_and_run(check_cancelled, newline_on_success, cache):
return 0 return 0
test_cache = (None if runs_per_test != 1 test_cache = (None
or 'gcov' in build_configs if not all(x.allow_hashing
or 'valgrind' in build_configs for x in itertools.chain(languages, run_configs))
else TestCache()) else TestCache())
if test_cache: if test_cache:
test_cache.maybe_load() test_cache.maybe_load()
@ -177,6 +218,7 @@ if forever:
'All tests are now passing properly', 'All tests are now passing properly',
do_newline=True) do_newline=True)
jobset.message('IDLE', 'No change detected') jobset.message('IDLE', 'No change detected')
if test_cache: test_cache.save()
while not have_files_changed(): while not have_files_changed():
time.sleep(1) time.sleep(1)
else: else:
@ -187,5 +229,5 @@ else:
jobset.message('SUCCESS', 'All tests passed', do_newline=True) jobset.message('SUCCESS', 'All tests passed', do_newline=True)
else: else:
jobset.message('FAILED', 'Some tests failed', do_newline=True) jobset.message('FAILED', 'Some tests failed', do_newline=True)
test_cache.save() if test_cache: test_cache.save()
sys.exit(result) sys.exit(result)

@ -0,0 +1,805 @@
[
{
"language": "c",
"name": "alarm_heap_test"
},
{
"language": "c",
"name": "alarm_list_test"
},
{
"language": "c",
"name": "alarm_test"
},
{
"language": "c",
"name": "alpn_test"
},
{
"language": "c",
"name": "bin_encoder_test"
},
{
"language": "c",
"name": "census_hash_table_test"
},
{
"language": "c",
"name": "census_statistics_multiple_writers_circular_buffer_test"
},
{
"language": "c",
"name": "census_statistics_multiple_writers_test"
},
{
"language": "c",
"name": "census_statistics_performance_test"
},
{
"language": "c",
"name": "census_statistics_quick_test"
},
{
"language": "c",
"name": "census_statistics_small_log_test"
},
{
"language": "c",
"name": "census_stub_test"
},
{
"language": "c",
"name": "census_window_stats_test"
},
{
"language": "c",
"name": "chttp2_status_conversion_test"
},
{
"language": "c",
"name": "chttp2_stream_encoder_test"
},
{
"language": "c",
"name": "chttp2_stream_map_test"
},
{
"language": "c",
"name": "chttp2_transport_end2end_test"
},
{
"language": "c",
"name": "dualstack_socket_test"
},
{
"language": "c",
"name": "echo_test"
},
{
"language": "c",
"name": "fd_posix_test"
},
{
"language": "c",
"name": "fling_stream_test"
},
{
"language": "c",
"name": "fling_test"
},
{
"language": "c",
"name": "gpr_cancellable_test"
},
{
"language": "c",
"name": "gpr_cmdline_test"
},
{
"language": "c",
"name": "gpr_histogram_test"
},
{
"language": "c",
"name": "gpr_host_port_test"
},
{
"language": "c",
"name": "gpr_log_test"
},
{
"language": "c",
"name": "gpr_slice_buffer_test"
},
{
"language": "c",
"name": "gpr_slice_test"
},
{
"language": "c",
"name": "gpr_string_test"
},
{
"language": "c",
"name": "gpr_sync_test"
},
{
"language": "c",
"name": "gpr_thd_test"
},
{
"language": "c",
"name": "gpr_time_test"
},
{
"language": "c",
"name": "gpr_useful_test"
},
{
"language": "c",
"name": "grpc_base64_test"
},
{
"language": "c",
"name": "grpc_byte_buffer_reader_test"
},
{
"language": "c",
"name": "grpc_channel_stack_test"
},
{
"language": "c",
"name": "grpc_completion_queue_test"
},
{
"language": "c",
"name": "grpc_credentials_test"
},
{
"language": "c",
"name": "grpc_json_token_test"
},
{
"language": "c",
"name": "grpc_stream_op_test"
},
{
"language": "c",
"name": "hpack_parser_test"
},
{
"language": "c",
"name": "hpack_table_test"
},
{
"language": "c",
"name": "httpcli_format_request_test"
},
{
"language": "c",
"name": "httpcli_parser_test"
},
{
"language": "c",
"name": "httpcli_test"
},
{
"language": "c",
"name": "lame_client_test"
},
{
"language": "c",
"name": "message_compress_test"
},
{
"language": "c",
"name": "metadata_buffer_test"
},
{
"language": "c",
"name": "murmur_hash_test"
},
{
"language": "c",
"name": "no_server_test"
},
{
"language": "c",
"name": "poll_kick_test"
},
{
"language": "c",
"name": "resolve_address_test"
},
{
"language": "c",
"name": "secure_endpoint_test"
},
{
"language": "c",
"name": "sockaddr_utils_test"
},
{
"language": "c",
"name": "tcp_client_posix_test"
},
{
"language": "c",
"name": "tcp_posix_test"
},
{
"language": "c",
"name": "tcp_server_posix_test"
},
{
"language": "c",
"name": "time_averaged_stats_test"
},
{
"language": "c",
"name": "time_test"
},
{
"language": "c",
"name": "timeout_encoding_test"
},
{
"language": "c",
"name": "transport_metadata_test"
},
{
"language": "c++",
"name": "channel_arguments_test"
},
{
"language": "c++",
"name": "credentials_test"
},
{
"language": "c++",
"name": "end2end_test"
},
{
"language": "c++",
"name": "status_test"
},
{
"language": "c++",
"name": "sync_client_async_server_test"
},
{
"language": "c++",
"name": "thread_pool_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_after_accept_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_after_accept_and_writes_closed_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_after_invoke_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_before_invoke_test"
},
{
"language": "c",
"name": "chttp2_fake_security_cancel_in_a_vacuum_test"
},
{
"language": "c",
"name": "chttp2_fake_security_census_simple_request_test"
},
{
"language": "c",
"name": "chttp2_fake_security_disappearing_server_test"
},
{
"language": "c",
"name": "chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test"
},
{
"language": "c",
"name": "chttp2_fake_security_early_server_shutdown_finishes_tags_test"
},
{
"language": "c",
"name": "chttp2_fake_security_graceful_server_shutdown_test"
},
{
"language": "c",
"name": "chttp2_fake_security_invoke_large_request_test"
},
{
"language": "c",
"name": "chttp2_fake_security_max_concurrent_streams_test"
},
{
"language": "c",
"name": "chttp2_fake_security_no_op_test"
},
{
"language": "c",
"name": "chttp2_fake_security_ping_pong_streaming_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_response_with_binary_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_response_with_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_response_with_payload_test"
},
{
"language": "c",
"name": "chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_fake_security_simple_delayed_request_test"
},
{
"language": "c",
"name": "chttp2_fake_security_simple_request_test"
},
{
"language": "c",
"name": "chttp2_fake_security_thread_stress_test"
},
{
"language": "c",
"name": "chttp2_fake_security_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_after_accept_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_after_accept_and_writes_closed_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_after_invoke_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_before_invoke_test"
},
{
"language": "c",
"name": "chttp2_fullstack_cancel_in_a_vacuum_test"
},
{
"language": "c",
"name": "chttp2_fullstack_census_simple_request_test"
},
{
"language": "c",
"name": "chttp2_fullstack_disappearing_server_test"
},
{
"language": "c",
"name": "chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test"
},
{
"language": "c",
"name": "chttp2_fullstack_early_server_shutdown_finishes_tags_test"
},
{
"language": "c",
"name": "chttp2_fullstack_graceful_server_shutdown_test"
},
{
"language": "c",
"name": "chttp2_fullstack_invoke_large_request_test"
},
{
"language": "c",
"name": "chttp2_fullstack_max_concurrent_streams_test"
},
{
"language": "c",
"name": "chttp2_fullstack_no_op_test"
},
{
"language": "c",
"name": "chttp2_fullstack_ping_pong_streaming_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_response_with_binary_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_response_with_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_response_with_payload_test"
},
{
"language": "c",
"name": "chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_fullstack_simple_delayed_request_test"
},
{
"language": "c",
"name": "chttp2_fullstack_simple_request_test"
},
{
"language": "c",
"name": "chttp2_fullstack_thread_stress_test"
},
{
"language": "c",
"name": "chttp2_fullstack_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_after_accept_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_after_invoke_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_before_invoke_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_census_simple_request_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_disappearing_server_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_graceful_server_shutdown_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_invoke_large_request_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_max_concurrent_streams_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_no_op_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_ping_pong_streaming_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_response_with_payload_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_simple_delayed_request_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_simple_request_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_thread_stress_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_no_op_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test"
},
{
"language": "c",
"name": "chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_after_accept_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_after_accept_and_writes_closed_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_after_invoke_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_before_invoke_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_cancel_in_a_vacuum_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_census_simple_request_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_disappearing_server_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_early_server_shutdown_finishes_tags_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_graceful_server_shutdown_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_invoke_large_request_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_max_concurrent_streams_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_no_op_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_ping_pong_streaming_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_response_with_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_response_with_payload_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_simple_delayed_request_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_simple_request_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_thread_stress_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_writes_done_hangs_with_pending_read_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_no_op_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_simple_request_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_thread_stress_test"
},
{
"language": "c",
"name": "chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test"
}
]

@ -17,22 +17,6 @@ echo Running test gpr_cancellable_test
test_bin\gpr_cancellable_test.exe || echo TEST FAILED: gpr_cancellable_test && exit /b test_bin\gpr_cancellable_test.exe || echo TEST FAILED: gpr_cancellable_test && exit /b
echo( echo(
echo Building test gpr_log_test
cl.exe /c /I..\.. /I..\..\include /nologo /ZI /W3 /WX- /sdl /D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- /Fo:test_bin\ ..\..\test\core\support\log_test.c
link.exe /OUT:"test_bin\gpr_log_test.exe" /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 Debug\gpr_test_util.lib Debug\gpr.lib test_bin\log_test.obj
echo(
echo Running test gpr_log_test
test_bin\gpr_log_test.exe || echo TEST FAILED: gpr_log_test && exit /b
echo(
echo Building test gpr_useful_test
cl.exe /c /I..\.. /I..\..\include /nologo /ZI /W3 /WX- /sdl /D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- /Fo:test_bin\ ..\..\test\core\support\useful_test.c
link.exe /OUT:"test_bin\gpr_useful_test.exe" /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 Debug\gpr_test_util.lib Debug\gpr.lib test_bin\useful_test.obj
echo(
echo Running test gpr_useful_test
test_bin\gpr_useful_test.exe || echo TEST FAILED: gpr_useful_test && exit /b
echo(
echo Building test gpr_cmdline_test echo Building test gpr_cmdline_test
cl.exe /c /I..\.. /I..\..\include /nologo /ZI /W3 /WX- /sdl /D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- /Fo:test_bin\ ..\..\test\core\support\cmdline_test.c cl.exe /c /I..\.. /I..\..\include /nologo /ZI /W3 /WX- /sdl /D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- /Fo:test_bin\ ..\..\test\core\support\cmdline_test.c
link.exe /OUT:"test_bin\gpr_cmdline_test.exe" /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 Debug\gpr_test_util.lib Debug\gpr.lib test_bin\cmdline_test.obj link.exe /OUT:"test_bin\gpr_cmdline_test.exe" /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 Debug\gpr_test_util.lib Debug\gpr.lib test_bin\cmdline_test.obj
@ -57,6 +41,14 @@ echo Running test gpr_host_port_test
test_bin\gpr_host_port_test.exe || echo TEST FAILED: gpr_host_port_test && exit /b test_bin\gpr_host_port_test.exe || echo TEST FAILED: gpr_host_port_test && exit /b
echo( echo(
echo Building test gpr_log_test
cl.exe /c /I..\.. /I..\..\include /nologo /ZI /W3 /WX- /sdl /D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- /Fo:test_bin\ ..\..\test\core\support\log_test.c
link.exe /OUT:"test_bin\gpr_log_test.exe" /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 Debug\gpr_test_util.lib Debug\gpr.lib test_bin\log_test.obj
echo(
echo Running test gpr_log_test
test_bin\gpr_log_test.exe || echo TEST FAILED: gpr_log_test && exit /b
echo(
echo Building test gpr_slice_buffer_test echo Building test gpr_slice_buffer_test
cl.exe /c /I..\.. /I..\..\include /nologo /ZI /W3 /WX- /sdl /D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- /Fo:test_bin\ ..\..\test\core\support\slice_buffer_test.c cl.exe /c /I..\.. /I..\..\include /nologo /ZI /W3 /WX- /sdl /D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- /Fo:test_bin\ ..\..\test\core\support\slice_buffer_test.c
link.exe /OUT:"test_bin\gpr_slice_buffer_test.exe" /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 Debug\gpr_test_util.lib Debug\gpr.lib test_bin\slice_buffer_test.obj link.exe /OUT:"test_bin\gpr_slice_buffer_test.exe" /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 Debug\gpr_test_util.lib Debug\gpr.lib test_bin\slice_buffer_test.obj
@ -105,3 +97,11 @@ echo Running test gpr_time_test
test_bin\gpr_time_test.exe || echo TEST FAILED: gpr_time_test && exit /b test_bin\gpr_time_test.exe || echo TEST FAILED: gpr_time_test && exit /b
echo( echo(
echo Building test gpr_useful_test
cl.exe /c /I..\.. /I..\..\include /nologo /ZI /W3 /WX- /sdl /D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- /Fo:test_bin\ ..\..\test\core\support\useful_test.c
link.exe /OUT:"test_bin\gpr_useful_test.exe" /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 Debug\gpr_test_util.lib Debug\gpr.lib test_bin\useful_test.obj
echo(
echo Running test gpr_useful_test
test_bin\gpr_useful_test.exe || echo TEST FAILED: gpr_useful_test && exit /b
echo(

@ -74,9 +74,9 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\include\grpc\support\alloc.h" /> <ClInclude Include="..\..\include\grpc\support\alloc.h" />
<ClInclude Include="..\..\include\grpc\support\atm.h" />
<ClInclude Include="..\..\include\grpc\support\atm_gcc_atomic.h" /> <ClInclude Include="..\..\include\grpc\support\atm_gcc_atomic.h" />
<ClInclude Include="..\..\include\grpc\support\atm_gcc_sync.h" /> <ClInclude Include="..\..\include\grpc\support\atm_gcc_sync.h" />
<ClInclude Include="..\..\include\grpc\support\atm.h" />
<ClInclude Include="..\..\include\grpc\support\atm_win32.h" /> <ClInclude Include="..\..\include\grpc\support\atm_win32.h" />
<ClInclude Include="..\..\include\grpc\support\cancellable_platform.h" /> <ClInclude Include="..\..\include\grpc\support\cancellable_platform.h" />
<ClInclude Include="..\..\include\grpc\support\cmdline.h" /> <ClInclude Include="..\..\include\grpc\support\cmdline.h" />
@ -84,11 +84,11 @@
<ClInclude Include="..\..\include\grpc\support\host_port.h" /> <ClInclude Include="..\..\include\grpc\support\host_port.h" />
<ClInclude Include="..\..\include\grpc\support\log.h" /> <ClInclude Include="..\..\include\grpc\support\log.h" />
<ClInclude Include="..\..\include\grpc\support\port_platform.h" /> <ClInclude Include="..\..\include\grpc\support\port_platform.h" />
<ClInclude Include="..\..\include\grpc\support\slice_buffer.h" />
<ClInclude Include="..\..\include\grpc\support\slice.h" /> <ClInclude Include="..\..\include\grpc\support\slice.h" />
<ClInclude Include="..\..\include\grpc\support\slice_buffer.h" />
<ClInclude Include="..\..\include\grpc\support\string.h" /> <ClInclude Include="..\..\include\grpc\support\string.h" />
<ClInclude Include="..\..\include\grpc\support\sync_generic.h" />
<ClInclude Include="..\..\include\grpc\support\sync.h" /> <ClInclude Include="..\..\include\grpc\support\sync.h" />
<ClInclude Include="..\..\include\grpc\support\sync_generic.h" />
<ClInclude Include="..\..\include\grpc\support\sync_posix.h" /> <ClInclude Include="..\..\include\grpc\support\sync_posix.h" />
<ClInclude Include="..\..\include\grpc\support\sync_win32.h" /> <ClInclude Include="..\..\include\grpc\support\sync_win32.h" />
<ClInclude Include="..\..\include\grpc\support\thd.h" /> <ClInclude Include="..\..\include\grpc\support\thd.h" />
@ -119,10 +119,10 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\support\host_port.c"> <ClCompile Include="..\..\src\core\support\host_port.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\support\log_android.c">
</ClCompile>
<ClCompile Include="..\..\src\core\support\log.c"> <ClCompile Include="..\..\src\core\support\log.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\support\log_android.c">
</ClCompile>
<ClCompile Include="..\..\src\core\support\log_linux.c"> <ClCompile Include="..\..\src\core\support\log_linux.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\support\log_posix.c"> <ClCompile Include="..\..\src\core\support\log_posix.c">
@ -131,10 +131,10 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\support\murmur_hash.c"> <ClCompile Include="..\..\src\core\support\murmur_hash.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\support\slice_buffer.c">
</ClCompile>
<ClCompile Include="..\..\src\core\support\slice.c"> <ClCompile Include="..\..\src\core\support\slice.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\support\slice_buffer.c">
</ClCompile>
<ClCompile Include="..\..\src\core\support\string.c"> <ClCompile Include="..\..\src\core\support\string.c">
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\core\support\string_posix.c"> <ClCompile Include="..\..\src\core\support\string_posix.c">

@ -5,20 +5,20 @@ VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr", "gpr.vcxproj", "{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr", "gpr.vcxproj", "{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_test_util", "gpr_test_util.vcxproj", "{EAB0A629-17A9-44DB-B5FF-E91A721FE037}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc", "grpc.vcxproj", "{29D16885-7228-4C31-81ED-5F9187C7F2A9}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc", "grpc.vcxproj", "{29D16885-7228-4C31-81ED-5F9187C7F2A9}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_test_util", "grpc_test_util.vcxproj", "{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "grpc_unsecure.vcxproj", "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "grpc_unsecure.vcxproj", "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_test_util", "gpr_test_util.vcxproj", "{EAB0A629-17A9-44DB-B5FF-E91A721FE037}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_test_util", "grpc_test_util.vcxproj", "{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "third_party\zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "third_party\zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "third_party", "third_party", "{DD51818F-0BCA-4035-9E5B-F28A9F87DED4}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "third_party", "third_party", "{DD51818F-0BCA-4035-9E5B-F28A9F87DED4}"
@ -33,22 +33,22 @@ Global
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}.Debug|Win32.Build.0 = Debug|Win32 {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}.Debug|Win32.Build.0 = Debug|Win32
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}.Release|Win32.ActiveCfg = Release|Win32 {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}.Release|Win32.ActiveCfg = Release|Win32
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}.Release|Win32.Build.0 = Release|Win32 {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}.Release|Win32.Build.0 = Release|Win32
{29D16885-7228-4C31-81ED-5F9187C7F2A9}.Debug|Win32.ActiveCfg = Debug|Win32
{29D16885-7228-4C31-81ED-5F9187C7F2A9}.Debug|Win32.Build.0 = Debug|Win32
{29D16885-7228-4C31-81ED-5F9187C7F2A9}.Release|Win32.ActiveCfg = Release|Win32
{29D16885-7228-4C31-81ED-5F9187C7F2A9}.Release|Win32.Build.0 = Release|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Debug|Win32.ActiveCfg = Debug|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Debug|Win32.Build.0 = Debug|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release|Win32.ActiveCfg = Release|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release|Win32.Build.0 = Release|Win32
{EAB0A629-17A9-44DB-B5FF-E91A721FE037}.Debug|Win32.ActiveCfg = Debug|Win32 {EAB0A629-17A9-44DB-B5FF-E91A721FE037}.Debug|Win32.ActiveCfg = Debug|Win32
{EAB0A629-17A9-44DB-B5FF-E91A721FE037}.Debug|Win32.Build.0 = Debug|Win32 {EAB0A629-17A9-44DB-B5FF-E91A721FE037}.Debug|Win32.Build.0 = Debug|Win32
{EAB0A629-17A9-44DB-B5FF-E91A721FE037}.Release|Win32.ActiveCfg = Release|Win32 {EAB0A629-17A9-44DB-B5FF-E91A721FE037}.Release|Win32.ActiveCfg = Release|Win32
{EAB0A629-17A9-44DB-B5FF-E91A721FE037}.Release|Win32.Build.0 = Release|Win32 {EAB0A629-17A9-44DB-B5FF-E91A721FE037}.Release|Win32.Build.0 = Release|Win32
{29D16885-7228-4C31-81ED-5F9187C7F2A9}.Debug|Win32.ActiveCfg = Debug|Win32
{29D16885-7228-4C31-81ED-5F9187C7F2A9}.Debug|Win32.Build.0 = Debug|Win32
{29D16885-7228-4C31-81ED-5F9187C7F2A9}.Release|Win32.ActiveCfg = Release|Win32
{29D16885-7228-4C31-81ED-5F9187C7F2A9}.Release|Win32.Build.0 = Release|Win32
{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}.Debug|Win32.ActiveCfg = Debug|Win32 {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}.Debug|Win32.ActiveCfg = Debug|Win32
{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}.Debug|Win32.Build.0 = Debug|Win32 {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}.Debug|Win32.Build.0 = Debug|Win32
{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}.Release|Win32.ActiveCfg = Release|Win32 {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}.Release|Win32.ActiveCfg = Release|Win32
{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}.Release|Win32.Build.0 = Release|Win32 {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}.Release|Win32.Build.0 = Release|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Debug|Win32.ActiveCfg = Debug|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Debug|Win32.Build.0 = Debug|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release|Win32.ActiveCfg = Release|Win32
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}.Release|Win32.Build.0 = Release|Win32
{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32
{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32
{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save