aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Yang Gao <yangg@google.com>2015-01-27 11:39:14 -0800
committerGravatar Yang Gao <yangg@google.com>2015-01-27 11:39:14 -0800
commit3ed874c861765726b0a86ff610988f56e00db4a2 (patch)
tree59cd01424e74d37bdcc89d6c2a9bd3341aa3de81
parentd785904d0a0bcd1b8c2a7dee7681131e8f9d3417 (diff)
parent9a9f4051203b4e8f38107d08c39b8a586e6a8dc9 (diff)
sync up with master
-rw-r--r--Makefile1
-rw-r--r--build.json2
-rw-r--r--examples/tips/client.h5
-rw-r--r--examples/tips/client_main.cc17
-rw-r--r--include/grpc/grpc_http.h67
-rw-r--r--src/core/channel/call_op_string.c99
-rw-r--r--src/core/channel/channel_args.c8
-rw-r--r--src/core/channel/channel_stack.c22
-rw-r--r--src/core/channel/channel_stack.h5
-rw-r--r--src/core/channel/connected_channel.c3
-rw-r--r--src/core/channel/http_client_filter.c12
-rw-r--r--src/core/channel/http_server_filter.c148
-rw-r--r--src/core/httpcli/format_request.c82
-rw-r--r--src/core/security/auth.c2
-rw-r--r--src/core/support/string.c48
-rw-r--r--src/core/support/string.h21
-rw-r--r--src/core/surface/call.c5
-rw-r--r--src/core/surface/call.h2
-rw-r--r--src/core/surface/event_string.c80
-rw-r--r--src/node/binding.gyp22
-rw-r--r--src/node/examples/math_server.js7
-rw-r--r--src/node/ext/byte_buffer.cc (renamed from src/node/byte_buffer.cc)0
-rw-r--r--src/node/ext/byte_buffer.h (renamed from src/node/byte_buffer.h)0
-rw-r--r--src/node/ext/call.cc (renamed from src/node/call.cc)0
-rw-r--r--src/node/ext/call.h (renamed from src/node/call.h)0
-rw-r--r--src/node/ext/channel.cc (renamed from src/node/channel.cc)0
-rw-r--r--src/node/ext/channel.h (renamed from src/node/channel.h)0
-rw-r--r--src/node/ext/completion_queue_async_worker.cc (renamed from src/node/completion_queue_async_worker.cc)0
-rw-r--r--src/node/ext/completion_queue_async_worker.h (renamed from src/node/completion_queue_async_worker.h)0
-rw-r--r--src/node/ext/credentials.cc (renamed from src/node/credentials.cc)0
-rw-r--r--src/node/ext/credentials.h (renamed from src/node/credentials.h)0
-rw-r--r--src/node/ext/event.cc (renamed from src/node/event.cc)0
-rw-r--r--src/node/ext/event.h (renamed from src/node/event.h)0
-rw-r--r--src/node/ext/node_grpc.cc (renamed from src/node/node_grpc.cc)0
-rw-r--r--src/node/ext/server.cc (renamed from src/node/server.cc)0
-rw-r--r--src/node/ext/server.h (renamed from src/node/server.h)0
-rw-r--r--src/node/ext/server_credentials.cc (renamed from src/node/server_credentials.cc)0
-rw-r--r--src/node/ext/server_credentials.h (renamed from src/node/server_credentials.h)0
-rw-r--r--src/node/ext/tag.cc (renamed from src/node/tag.cc)0
-rw-r--r--src/node/ext/tag.h (renamed from src/node/tag.h)0
-rw-r--r--src/node/ext/timeval.cc (renamed from src/node/timeval.cc)0
-rw-r--r--src/node/ext/timeval.h (renamed from src/node/timeval.h)0
-rw-r--r--src/node/index.js (renamed from src/node/main.js)4
-rw-r--r--src/node/interop/interop_client.js2
-rw-r--r--src/node/package.json2
-rw-r--r--src/node/src/client.js (renamed from src/node/client.js)14
-rw-r--r--src/node/src/common.js (renamed from src/node/common.js)0
-rw-r--r--src/node/src/server.js (renamed from src/node/server.js)5
-rw-r--r--src/node/src/surface_client.js (renamed from src/node/surface_client.js)132
-rw-r--r--src/node/src/surface_server.js (renamed from src/node/surface_server.js)145
-rw-r--r--src/node/test/call_test.js13
-rw-r--r--src/node/test/client_server_test.js98
-rw-r--r--src/node/test/end_to_end_test.js21
-rw-r--r--src/node/test/interop_sanity_test.js5
-rw-r--r--src/node/test/server_test.js15
-rw-r--r--src/node/test/surface_test.js55
-rwxr-xr-xsrc/ruby/README.md27
-rwxr-xr-xsrc/ruby/bin/interop/interop_client.rb99
-rwxr-xr-xsrc/ruby/bin/interop/interop_server.rb19
-rw-r--r--src/ruby/ext/grpc/rb_credentials.c17
-rw-r--r--src/ruby/ext/grpc/rb_server.c12
-rwxr-xr-xsrc/ruby/grpc.gemspec1
-rw-r--r--src/ruby/lib/grpc/generic/active_call.rb2
-rw-r--r--src/ruby/spec/call_spec.rb26
-rw-r--r--src/ruby/spec/channel_spec.rb21
-rw-r--r--src/ruby/spec/client_server_spec.rb102
-rw-r--r--src/ruby/spec/generic/active_call_spec.rb10
-rw-r--r--src/ruby/spec/generic/client_stub_spec.rb144
-rw-r--r--src/ruby/spec/generic/rpc_server_spec.rb7
-rw-r--r--src/ruby/spec/port_picker.rb45
-rw-r--r--src/ruby/spec/server_spec.rb5
-rw-r--r--test/core/channel/metadata_buffer_test.c9
-rw-r--r--test/core/echo/server.c69
-rw-r--r--test/core/end2end/cq_verifier.c126
-rw-r--r--test/core/end2end/tests/census_simple_request.c6
-rw-r--r--test/core/end2end/tests/simple_request.c6
-rw-r--r--test/core/security/credentials_test.c6
-rw-r--r--test/core/statistics/hash_table_test.c7
-rw-r--r--test/core/transport/chttp2/hpack_table_test.c21
-rw-r--r--test/core/transport/chttp2/stream_encoder_test.c17
-rw-r--r--test/core/transport/chttp2/timeout_encoding_test.c19
-rw-r--r--test/core/transport/metadata_test.c19
-rwxr-xr-xtools/clang-format/clang-format-all.sh9
-rw-r--r--tools/clang-format/config.sh11
-rw-r--r--tools/dockerfile/grpc_java/Dockerfile5
-rw-r--r--tools/dockerfile/grpc_java_base/Dockerfile18
-rw-r--r--tools/dockerfile/grpc_ruby/Dockerfile8
-rwxr-xr-xtools/gce_setup/cloud_prod_runner.sh24
-rwxr-xr-xtools/gce_setup/grpc_docker.sh144
-rwxr-xr-xtools/gce_setup/interop_test_runner.sh28
-rwxr-xr-xtools/gce_setup/shared_startup_funcs.sh38
-rwxr-xr-xtools/run_tests/build_node.sh7
-rwxr-xr-xtools/run_tests/build_php.sh8
-rwxr-xr-xtools/run_tests/run_lcov.sh2
-rwxr-xr-xtools/run_tests/run_node.sh10
-rwxr-xr-xtools/run_tests/run_tests.py24
-rw-r--r--vsprojects/vs2013/gpr.vcxproj2
-rw-r--r--vsprojects/vs2013/gpr.vcxproj.filters6
98 files changed, 1478 insertions, 877 deletions
diff --git a/Makefile b/Makefile
index f4bb942b52..74372a6fb8 100644
--- a/Makefile
+++ b/Makefile
@@ -1233,7 +1233,6 @@ PUBLIC_HEADERS_C += \
include/grpc/support/port_platform.h \
include/grpc/support/slice.h \
include/grpc/support/slice_buffer.h \
- include/grpc/support/string.h \
include/grpc/support/sync.h \
include/grpc/support/sync_generic.h \
include/grpc/support/sync_posix.h \
diff --git a/build.json b/build.json
index 4416c3fdd4..b90b1ca92e 100644
--- a/build.json
+++ b/build.json
@@ -202,7 +202,6 @@
"include/grpc/support/port_platform.h",
"include/grpc/support/slice.h",
"include/grpc/support/slice_buffer.h",
- "include/grpc/support/string.h",
"include/grpc/support/sync.h",
"include/grpc/support/sync_generic.h",
"include/grpc/support/sync_posix.h",
@@ -218,6 +217,7 @@
"headers": [
"src/core/support/cpu.h",
"src/core/support/murmur_hash.h",
+ "src/core/support/string.h",
"src/core/support/thd_internal.h"
],
"src": [
diff --git a/examples/tips/client.h b/examples/tips/client.h
index 3f4f1fd836..6ae9d50658 100644
--- a/examples/tips/client.h
+++ b/examples/tips/client.h
@@ -31,6 +31,9 @@
*
*/
+#ifndef __GRPCPP_EXAMPLES_TIPS_CLIENT_H_
+#define __GRPCPP_EXAMPLES_TIPS_CLIENT_H_
+
#include <grpc++/channel_interface.h>
#include <grpc++/status.h>
@@ -52,3 +55,5 @@ class Client {
} // namespace tips
} // namespace examples
} // namespace grpc
+
+#endif // __GRPCPP_EXAMPLES_TIPS_CLIENT_H_
diff --git a/examples/tips/client_main.cc b/examples/tips/client_main.cc
index 17567b6f17..f4a3b09601 100644
--- a/examples/tips/client_main.cc
+++ b/examples/tips/client_main.cc
@@ -41,30 +41,29 @@
#include "examples/tips/client.h"
#include "test/cpp/util/create_test_channel.h"
-DEFINE_bool(enable_ssl, true, "Whether to use ssl/tls.");
-DEFINE_bool(use_prod_roots, true, "True to use SSL roots for production GFE");
-DEFINE_int32(server_port, 0, "Server port.");
-DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
-DEFINE_string(server_host_override, "foo.test.google.com",
- "Override the server host which is sent in HTTP header");
+DEFINE_int32(server_port, 443, "Server port.");
+DEFINE_string(server_host,
+ "pubsub-staging.googleapis.com", "Server host to connect to");
int main(int argc, char** argv) {
grpc_init();
google::ParseCommandLineFlags(&argc, &argv, true);
gpr_log(GPR_INFO, "Start TIPS client");
- GPR_ASSERT(FLAGS_server_port);
const int host_port_buf_size = 1024;
char host_port[host_port_buf_size];
snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
FLAGS_server_port);
std::shared_ptr<grpc::ChannelInterface> channel(
- grpc::CreateTestChannel(host_port, FLAGS_server_host_override,
- FLAGS_enable_ssl, FLAGS_use_prod_roots));
+ grpc::CreateTestChannel(host_port,
+ FLAGS_server_host,
+ true, // enable SSL
+ true)); // use prod roots
grpc::examples::tips::Client client(channel);
grpc::Status s = client.CreateTopic("test");
+ gpr_log(GPR_INFO, "return code %d", s.code());
GPR_ASSERT(s.IsOk());
channel.reset();
diff --git a/include/grpc/grpc_http.h b/include/grpc/grpc_http.h
new file mode 100644
index 0000000000..b2ae5340a5
--- /dev/null
+++ b/include/grpc/grpc_http.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GRPC_GRPC_HTTP_H__
+#define __GRPC_GRPC_HTTP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* HTTP GET support.
+
+ HTTP2 servers can publish statically generated text content served
+ via HTTP2 GET queries by publishing one or more grpc_http_server_page
+ elements via repeated GRPC_ARG_SERVE_OVER_HTTP elements in the servers
+ channel_args.
+
+ This is not:
+ - a general purpose web server
+ - particularly fast
+
+ It's useful for being able to serve up some static content (maybe some
+ javascript to be able to interact with your GRPC server?) */
+
+typedef struct {
+ const char *path;
+ const char *content_type;
+ const char *content;
+} grpc_http_server_page;
+
+#define GRPC_ARG_SERVE_OVER_HTTP "grpc.serve_over_http"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GRPC_GRPC_HTTP_H__ */
diff --git a/src/core/channel/call_op_string.c b/src/core/channel/call_op_string.c
index 789913901a..127ea707bf 100644
--- a/src/core/channel/call_op_string.c
+++ b/src/core/channel/call_op_string.c
@@ -41,110 +41,89 @@
#include <grpc/support/alloc.h>
#include <grpc/support/useful.h>
-#define MAX_APPEND 1024
+static void put_metadata(gpr_strvec *b, grpc_mdelem *md) {
+ gpr_strvec_add(b, gpr_strdup(" key="));
+ gpr_strvec_add(b, gpr_hexdump((char *)GPR_SLICE_START_PTR(md->key->slice),
+ GPR_SLICE_LENGTH(md->key->slice), GPR_HEXDUMP_PLAINTEXT));
-typedef struct {
- size_t cap;
- size_t len;
- char *buffer;
-} buf;
-
-static void bprintf(buf *b, const char *fmt, ...) {
- va_list arg;
- if (b->len + MAX_APPEND > b->cap) {
- b->cap = GPR_MAX(b->len + MAX_APPEND, b->cap * 3 / 2);
- b->buffer = gpr_realloc(b->buffer, b->cap);
- }
- va_start(arg, fmt);
- b->len += vsprintf(b->buffer + b->len, fmt, arg);
- va_end(arg);
-}
-
-static void bputs(buf *b, const char *s) {
- size_t slen = strlen(s);
- if (b->len + slen + 1 > b->cap) {
- b->cap = GPR_MAX(b->len + slen + 1, b->cap * 3 / 2);
- b->buffer = gpr_realloc(b->buffer, b->cap);
- }
- strcat(b->buffer, s);
- b->len += slen;
-}
-
-static void put_metadata(buf *b, grpc_mdelem *md) {
- char *txt;
-
- txt = gpr_hexdump((char *)GPR_SLICE_START_PTR(md->key->slice),
- GPR_SLICE_LENGTH(md->key->slice), GPR_HEXDUMP_PLAINTEXT);
- bputs(b, " key=");
- bputs(b, txt);
- gpr_free(txt);
-
- txt = gpr_hexdump((char *)GPR_SLICE_START_PTR(md->value->slice),
- GPR_SLICE_LENGTH(md->value->slice), GPR_HEXDUMP_PLAINTEXT);
- bputs(b, " value=");
- bputs(b, txt);
- gpr_free(txt);
+ gpr_strvec_add(b, gpr_strdup(" value="));
+ gpr_strvec_add(b, gpr_hexdump((char *)GPR_SLICE_START_PTR(md->value->slice),
+ GPR_SLICE_LENGTH(md->value->slice), GPR_HEXDUMP_PLAINTEXT));
}
char *grpc_call_op_string(grpc_call_op *op) {
- buf b = {0, 0, 0};
+ char *tmp;
+ char *out;
+
+ gpr_strvec b;
+ gpr_strvec_init(&b);
switch (op->dir) {
case GRPC_CALL_DOWN:
- bprintf(&b, ">");
+ gpr_strvec_add(&b, gpr_strdup(">"));
break;
case GRPC_CALL_UP:
- bprintf(&b, "<");
+ gpr_strvec_add(&b, gpr_strdup("<"));
break;
}
switch (op->type) {
case GRPC_SEND_METADATA:
- bprintf(&b, "SEND_METADATA");
+ gpr_strvec_add(&b, gpr_strdup("SEND_METADATA"));
put_metadata(&b, op->data.metadata);
break;
case GRPC_SEND_DEADLINE:
- bprintf(&b, "SEND_DEADLINE %d.%09d", op->data.deadline.tv_sec,
+ gpr_asprintf(&tmp, "SEND_DEADLINE %d.%09d", op->data.deadline.tv_sec,
op->data.deadline.tv_nsec);
+ gpr_strvec_add(&b, tmp);
break;
case GRPC_SEND_START:
- bprintf(&b, "SEND_START pollset=%p", op->data.start.pollset);
+ gpr_asprintf(&tmp, "SEND_START pollset=%p", op->data.start.pollset);
+ gpr_strvec_add(&b, tmp);
break;
case GRPC_SEND_MESSAGE:
- bprintf(&b, "SEND_MESSAGE");
+ gpr_strvec_add(&b, gpr_strdup("SEND_MESSAGE"));
+ break;
+ case GRPC_SEND_PREFORMATTED_MESSAGE:
+ gpr_strvec_add(&b, gpr_strdup("SEND_PREFORMATTED_MESSAGE"));
break;
case GRPC_SEND_FINISH:
- bprintf(&b, "SEND_FINISH");
+ gpr_strvec_add(&b, gpr_strdup("SEND_FINISH"));
break;
case GRPC_REQUEST_DATA:
- bprintf(&b, "REQUEST_DATA");
+ gpr_strvec_add(&b, gpr_strdup("REQUEST_DATA"));
break;
case GRPC_RECV_METADATA:
- bprintf(&b, "RECV_METADATA");
+ gpr_strvec_add(&b, gpr_strdup("RECV_METADATA"));
put_metadata(&b, op->data.metadata);
break;
case GRPC_RECV_DEADLINE:
- bprintf(&b, "RECV_DEADLINE %d.%09d", op->data.deadline.tv_sec,
+ gpr_asprintf(&tmp, "RECV_DEADLINE %d.%09d", op->data.deadline.tv_sec,
op->data.deadline.tv_nsec);
+ gpr_strvec_add(&b, tmp);
break;
case GRPC_RECV_END_OF_INITIAL_METADATA:
- bprintf(&b, "RECV_END_OF_INITIAL_METADATA");
+ gpr_strvec_add(&b, gpr_strdup("RECV_END_OF_INITIAL_METADATA"));
break;
case GRPC_RECV_MESSAGE:
- bprintf(&b, "RECV_MESSAGE");
+ gpr_strvec_add(&b, gpr_strdup("RECV_MESSAGE"));
break;
case GRPC_RECV_HALF_CLOSE:
- bprintf(&b, "RECV_HALF_CLOSE");
+ gpr_strvec_add(&b, gpr_strdup("RECV_HALF_CLOSE"));
break;
case GRPC_RECV_FINISH:
- bprintf(&b, "RECV_FINISH");
+ gpr_strvec_add(&b, gpr_strdup("RECV_FINISH"));
break;
case GRPC_CANCEL_OP:
- bprintf(&b, "CANCEL_OP");
+ gpr_strvec_add(&b, gpr_strdup("CANCEL_OP"));
break;
}
- bprintf(&b, " flags=0x%08x", op->flags);
+ gpr_asprintf(&tmp, " flags=0x%08x", op->flags);
+ gpr_strvec_add(&b, tmp);
+
+ out = gpr_strvec_flatten(&b, NULL);
+ gpr_strvec_destroy(&b);
- return b.buffer;
+ return out;
}
void grpc_call_log_op(char *file, int line, gpr_log_severity severity,
diff --git a/src/core/channel/channel_args.c b/src/core/channel/channel_args.c
index 04ce519ff3..5f16c7b7e9 100644
--- a/src/core/channel/channel_args.c
+++ b/src/core/channel/channel_args.c
@@ -52,7 +52,9 @@ static grpc_arg copy_arg(const grpc_arg *src) {
break;
case GRPC_ARG_POINTER:
dst.value.pointer = src->value.pointer;
- dst.value.pointer.p = src->value.pointer.copy(src->value.pointer.p);
+ dst.value.pointer.p = src->value.pointer.copy
+ ? src->value.pointer.copy(src->value.pointer.p)
+ : src->value.pointer.p;
break;
}
return dst;
@@ -91,7 +93,9 @@ void grpc_channel_args_destroy(grpc_channel_args *a) {
case GRPC_ARG_INTEGER:
break;
case GRPC_ARG_POINTER:
- a->args[i].value.pointer.destroy(a->args[i].value.pointer.p);
+ if (a->args[i].value.pointer.destroy) {
+ a->args[i].value.pointer.destroy(a->args[i].value.pointer.p);
+ }
break;
}
gpr_free(a->args[i].key);
diff --git a/src/core/channel/channel_stack.c b/src/core/channel/channel_stack.c
index 0134b9ab44..af47df844a 100644
--- a/src/core/channel/channel_stack.c
+++ b/src/core/channel/channel_stack.c
@@ -202,6 +202,17 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) {
static void do_nothing(void *user_data, grpc_op_error error) {}
+void grpc_call_element_recv_metadata(grpc_call_element *cur_elem,
+ grpc_mdelem *mdelem) {
+ grpc_call_op metadata_op;
+ metadata_op.type = GRPC_RECV_METADATA;
+ metadata_op.dir = GRPC_CALL_UP;
+ metadata_op.done_cb = do_nothing;
+ metadata_op.user_data = NULL;
+ metadata_op.data.metadata = mdelem;
+ grpc_call_next_op(cur_elem, &metadata_op);
+}
+
void grpc_call_element_send_metadata(grpc_call_element *cur_elem,
grpc_mdelem *mdelem) {
grpc_call_op metadata_op;
@@ -209,7 +220,7 @@ void grpc_call_element_send_metadata(grpc_call_element *cur_elem,
metadata_op.dir = GRPC_CALL_DOWN;
metadata_op.done_cb = do_nothing;
metadata_op.user_data = NULL;
- metadata_op.data.metadata = grpc_mdelem_ref(mdelem);
+ metadata_op.data.metadata = mdelem;
grpc_call_next_op(cur_elem, &metadata_op);
}
@@ -221,3 +232,12 @@ void grpc_call_element_send_cancel(grpc_call_element *cur_elem) {
cancel_op.user_data = NULL;
grpc_call_next_op(cur_elem, &cancel_op);
}
+
+void grpc_call_element_send_finish(grpc_call_element *cur_elem) {
+ grpc_call_op cancel_op;
+ cancel_op.type = GRPC_SEND_FINISH;
+ cancel_op.dir = GRPC_CALL_DOWN;
+ cancel_op.done_cb = do_nothing;
+ cancel_op.user_data = NULL;
+ grpc_call_next_op(cur_elem, &cancel_op);
+}
diff --git a/src/core/channel/channel_stack.h b/src/core/channel/channel_stack.h
index 12ada95813..ec9ecf3d15 100644
--- a/src/core/channel/channel_stack.h
+++ b/src/core/channel/channel_stack.h
@@ -69,6 +69,8 @@ typedef enum {
GRPC_SEND_START,
/* send a message to the channels peer */
GRPC_SEND_MESSAGE,
+ /* send a pre-formatted message to the channels peer */
+ GRPC_SEND_PREFORMATTED_MESSAGE,
/* send half-close to the channels peer */
GRPC_SEND_FINISH,
/* request that more data be allowed through flow control */
@@ -294,7 +296,10 @@ void grpc_call_log_op(char *file, int line, gpr_log_severity severity,
void grpc_call_element_send_metadata(grpc_call_element *cur_elem,
grpc_mdelem *elem);
+void grpc_call_element_recv_metadata(grpc_call_element *cur_elem,
+ grpc_mdelem *elem);
void grpc_call_element_send_cancel(grpc_call_element *cur_elem);
+void grpc_call_element_send_finish(grpc_call_element *cur_elem);
#ifdef GRPC_CHANNEL_STACK_TRACE
#define GRPC_CALL_LOG_OP(sev, elem, op) grpc_call_log_op(sev, elem, op)
diff --git a/src/core/channel/connected_channel.c b/src/core/channel/connected_channel.c
index d48269b743..d35cede97b 100644
--- a/src/core/channel/connected_channel.c
+++ b/src/core/channel/connected_channel.c
@@ -140,6 +140,8 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
grpc_sopb_add_begin_message(&calld->outgoing_sopb,
grpc_byte_buffer_length(op->data.message),
op->flags);
+ /* fall-through */
+ case GRPC_SEND_PREFORMATTED_MESSAGE:
copy_byte_buffer_to_stream_ops(op->data.message, &calld->outgoing_sopb);
calld->outgoing_buffer_length_estimate +=
(5 + grpc_byte_buffer_length(op->data.message));
@@ -445,6 +447,7 @@ static void recv_batch(void *user_data, grpc_transport *transport,
(int)calld->incoming_message.length,
(int)calld->incoming_message_length);
recv_error(chand, calld, __LINE__, message);
+ gpr_free(message);
}
call_op.type = GRPC_RECV_HALF_CLOSE;
call_op.dir = GRPC_CALL_UP;
diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c
index bd1c1f0a6b..4735aa939c 100644
--- a/src/core/channel/http_client_filter.c
+++ b/src/core/channel/http_client_filter.c
@@ -69,8 +69,8 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
/* Send : prefixed headers, which have to be before any application
* layer headers. */
calld->sent_headers = 1;
- grpc_call_element_send_metadata(elem, channeld->method);
- grpc_call_element_send_metadata(elem, channeld->scheme);
+ grpc_call_element_send_metadata(elem, grpc_mdelem_ref(channeld->method));
+ grpc_call_element_send_metadata(elem, grpc_mdelem_ref(channeld->scheme));
}
grpc_call_next_op(elem, op);
break;
@@ -78,12 +78,12 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
if (!calld->sent_headers) {
/* Send : prefixed headers, if we haven't already */
calld->sent_headers = 1;
- grpc_call_element_send_metadata(elem, channeld->method);
- grpc_call_element_send_metadata(elem, channeld->scheme);
+ grpc_call_element_send_metadata(elem, grpc_mdelem_ref(channeld->method));
+ grpc_call_element_send_metadata(elem, grpc_mdelem_ref(channeld->scheme));
}
/* Send non : prefixed headers */
- grpc_call_element_send_metadata(elem, channeld->te_trailers);
- grpc_call_element_send_metadata(elem, channeld->content_type);
+ grpc_call_element_send_metadata(elem, grpc_mdelem_ref(channeld->te_trailers));
+ grpc_call_element_send_metadata(elem, grpc_mdelem_ref(channeld->content_type));
grpc_call_next_op(elem, op);
break;
default:
diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c
index a136496f23..2658a6d42e 100644
--- a/src/core/channel/http_server_filter.c
+++ b/src/core/channel/http_server_filter.c
@@ -34,29 +34,80 @@
#include "src/core/channel/http_server_filter.h"
#include <string.h>
+#include <grpc/grpc_http.h>
+#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+typedef enum { NOT_RECEIVED, POST, GET } known_method_type;
+
+typedef struct {
+ grpc_mdelem *path;
+ grpc_mdelem *content_type;
+ grpc_byte_buffer *content;
+} gettable;
+
typedef struct call_data {
- int sent_status;
- int seen_scheme;
- int seen_method;
- int seen_te_trailers;
+ known_method_type seen_method;
+ gpr_uint8 sent_status;
+ gpr_uint8 seen_scheme;
+ gpr_uint8 seen_te_trailers;
+ grpc_mdelem *path;
} call_data;
typedef struct channel_data {
grpc_mdelem *te_trailers;
- grpc_mdelem *method;
+ grpc_mdelem *method_get;
+ grpc_mdelem *method_post;
grpc_mdelem *http_scheme;
grpc_mdelem *https_scheme;
/* TODO(klempner): Remove this once we stop using it */
grpc_mdelem *grpc_scheme;
grpc_mdelem *content_type;
- grpc_mdelem *status;
+ grpc_mdelem *status_ok;
+ grpc_mdelem *status_not_found;
+ grpc_mdstr *path_key;
+
+ size_t gettable_count;
+ gettable *gettables;
} channel_data;
/* used to silence 'variable not used' warnings */
static void ignore_unused(void *ignored) {}
+/* Handle 'GET': not technically grpc, so probably a web browser hitting
+ us */
+static void payload_done(void *elem, grpc_op_error error) {
+ if (error == GRPC_OP_OK) {
+ grpc_call_element_send_finish(elem);
+ }
+}
+
+static void handle_get(grpc_call_element *elem) {
+ channel_data *channeld = elem->channel_data;
+ call_data *calld = elem->call_data;
+ grpc_call_op op;
+ size_t i;
+
+ for (i = 0; i < channeld->gettable_count; i++) {
+ if (channeld->gettables[i].path == calld->path) {
+ grpc_call_element_send_metadata(elem,
+ grpc_mdelem_ref(channeld->status_ok));
+ grpc_call_element_send_metadata(
+ elem, grpc_mdelem_ref(channeld->gettables[i].content_type));
+ op.type = GRPC_SEND_PREFORMATTED_MESSAGE;
+ op.dir = GRPC_CALL_DOWN;
+ op.flags = 0;
+ op.data.message = channeld->gettables[i].content;
+ op.done_cb = payload_done;
+ op.user_data = elem;
+ grpc_call_next_op(elem, &op);
+ }
+ }
+ grpc_call_element_send_metadata(elem,
+ grpc_mdelem_ref(channeld->status_not_found));
+ grpc_call_element_send_finish(elem);
+}
+
/* Called either:
- in response to an API call (or similar) from above, to send something
- a network event (or similar) from below, to receive something
@@ -73,14 +124,17 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
case GRPC_RECV_METADATA:
/* Check if it is one of the headers we care about. */
if (op->data.metadata == channeld->te_trailers ||
- op->data.metadata == channeld->method ||
+ op->data.metadata == channeld->method_get ||
+ op->data.metadata == channeld->method_post ||
op->data.metadata == channeld->http_scheme ||
op->data.metadata == channeld->https_scheme ||
op->data.metadata == channeld->grpc_scheme ||
op->data.metadata == channeld->content_type) {
/* swallow it */
- if (op->data.metadata == channeld->method) {
- calld->seen_method = 1;
+ if (op->data.metadata == channeld->method_get) {
+ calld->seen_method = GET;
+ } else if (op->data.metadata == channeld->method_post) {
+ calld->seen_method = POST;
} else if (op->data.metadata->key == channeld->http_scheme->key) {
calld->seen_scheme = 1;
} else if (op->data.metadata == channeld->te_trailers) {
@@ -108,7 +162,7 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
grpc_mdelem_unref(op->data.metadata);
op->done_cb(op->user_data, GRPC_OP_OK);
} else if (op->data.metadata->key == channeld->te_trailers->key ||
- op->data.metadata->key == channeld->method->key ||
+ op->data.metadata->key == channeld->method_post->key ||
op->data.metadata->key == channeld->http_scheme->key ||
op->data.metadata->key == channeld->content_type->key) {
gpr_log(GPR_ERROR, "Invalid %s: header: '%s'",
@@ -120,6 +174,13 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
grpc_mdelem_unref(op->data.metadata);
op->done_cb(op->user_data, GRPC_OP_OK);
grpc_call_element_send_cancel(elem);
+ } else if (op->data.metadata->key == channeld->path_key) {
+ if (calld->path != NULL) {
+ gpr_log(GPR_ERROR, "Received :path twice");
+ grpc_mdelem_unref(calld->path);
+ }
+ calld->path = op->data.metadata;
+ op->done_cb(op->user_data, GRPC_OP_OK);
} else {
/* pass the event up */
grpc_call_next_op(elem, op);
@@ -129,14 +190,21 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
/* Have we seen the required http2 transport headers?
(:method, :scheme, content-type, with :path and :authority covered
at the channel level right now) */
- if (calld->seen_method && calld->seen_scheme && calld->seen_te_trailers) {
+ if (calld->seen_method == POST && calld->seen_scheme &&
+ calld->seen_te_trailers && calld->path) {
+ grpc_call_element_recv_metadata(elem, calld->path);
+ calld->path = NULL;
grpc_call_next_op(elem, op);
+ } else if (calld->seen_method == GET) {
+ handle_get(elem);
} else {
- if (!calld->seen_method) {
+ if (calld->seen_method == NOT_RECEIVED) {
gpr_log(GPR_ERROR, "Missing :method header");
- } else if (!calld->seen_scheme) {
+ }
+ if (!calld->seen_scheme) {
gpr_log(GPR_ERROR, "Missing :scheme header");
- } else if (!calld->seen_te_trailers) {
+ }
+ if (!calld->seen_te_trailers) {
gpr_log(GPR_ERROR, "Missing te trailers header");
}
/* Error this call out */
@@ -151,7 +219,8 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
if (!calld->sent_status) {
calld->sent_status = 1;
/* status is reffed by grpc_call_element_send_metadata */
- grpc_call_element_send_metadata(elem, channeld->status);
+ grpc_call_element_send_metadata(elem,
+ grpc_mdelem_ref(channeld->status_ok));
}
grpc_call_next_op(elem, op);
break;
@@ -189,9 +258,10 @@ static void init_call_elem(grpc_call_element *elem,
ignore_unused(channeld);
/* initialize members */
+ calld->path = NULL;
calld->sent_status = 0;
calld->seen_scheme = 0;
- calld->seen_method = 0;
+ calld->seen_method = NOT_RECEIVED;
calld->seen_te_trailers = 0;
}
@@ -201,14 +271,20 @@ static void destroy_call_elem(grpc_call_element *elem) {
call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data;
- ignore_unused(calld);
ignore_unused(channeld);
+
+ if (calld->path) {
+ grpc_mdelem_unref(calld->path);
+ }
}
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
+ size_t i;
+ size_t gettable_capacity = 0;
+
/* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data;
@@ -220,13 +296,40 @@ static void init_channel_elem(grpc_channel_element *elem,
/* initialize members */
channeld->te_trailers = grpc_mdelem_from_strings(mdctx, "te", "trailers");
- channeld->status = grpc_mdelem_from_strings(mdctx, ":status", "200");
- channeld->method = grpc_mdelem_from_strings(mdctx, ":method", "POST");
+ channeld->status_ok = grpc_mdelem_from_strings(mdctx, ":status", "200");
+ channeld->status_not_found =
+ grpc_mdelem_from_strings(mdctx, ":status", "404");
+ channeld->method_post = grpc_mdelem_from_strings(mdctx, ":method", "POST");
+ channeld->method_get = grpc_mdelem_from_strings(mdctx, ":method", "GET");
channeld->http_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "http");
channeld->https_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "https");
channeld->grpc_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "grpc");
+ channeld->path_key = grpc_mdstr_from_string(mdctx, ":path");
channeld->content_type =
grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
+
+ /* initialize http download support */
+ channeld->gettable_count = 0;
+ channeld->gettables = NULL;
+ for (i = 0; i < args->num_args; i++) {
+ if (0 == strcmp(args->args[i].key, GRPC_ARG_SERVE_OVER_HTTP)) {
+ gettable *g;
+ gpr_slice slice;
+ grpc_http_server_page *p = args->args[i].value.pointer.p;
+ if (channeld->gettable_count == gettable_capacity) {
+ gettable_capacity =
+ GPR_MAX(gettable_capacity * 3 / 2, gettable_capacity + 1);
+ channeld->gettables =
+ gpr_realloc(channeld->gettables, gettable_capacity * sizeof(gettable));
+ }
+ g = &channeld->gettables[channeld->gettable_count++];
+ g->path = grpc_mdelem_from_strings(mdctx, ":path", p->path);
+ g->content_type =
+ grpc_mdelem_from_strings(mdctx, "content-type", p->content_type);
+ slice = gpr_slice_from_copied_string(p->content);
+ g->content = grpc_byte_buffer_create(&slice, 1);
+ }
+ }
}
/* Destructor for channel data */
@@ -235,12 +338,15 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
channel_data *channeld = elem->channel_data;
grpc_mdelem_unref(channeld->te_trailers);
- grpc_mdelem_unref(channeld->status);
- grpc_mdelem_unref(channeld->method);
+ grpc_mdelem_unref(channeld->status_ok);
+ grpc_mdelem_unref(channeld->status_not_found);
+ grpc_mdelem_unref(channeld->method_post);
+ grpc_mdelem_unref(channeld->method_get);
grpc_mdelem_unref(channeld->http_scheme);
grpc_mdelem_unref(channeld->https_scheme);
grpc_mdelem_unref(channeld->grpc_scheme);
grpc_mdelem_unref(channeld->content_type);
+ grpc_mdstr_unref(channeld->path_key);
}
const grpc_channel_filter grpc_http_server_filter = {
diff --git a/src/core/httpcli/format_request.c b/src/core/httpcli/format_request.c
index 7a44f1266f..58bb7c740e 100644
--- a/src/core/httpcli/format_request.c
+++ b/src/core/httpcli/format_request.c
@@ -37,67 +37,57 @@
#include <stdio.h>
#include <string.h>
+#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/slice.h>
#include <grpc/support/useful.h>
-typedef struct {
- size_t length;
- size_t capacity;
- char *data;
-} sbuf;
-
-static void sbuf_append(sbuf *buf, const char *bytes, size_t len) {
- if (buf->length + len > buf->capacity) {
- buf->capacity = GPR_MAX(buf->length + len, buf->capacity * 3 / 2);
- buf->data = gpr_realloc(buf->data, buf->capacity);
- }
- memcpy(buf->data + buf->length, bytes, len);
- buf->length += len;
-}
-
-static void sbprintf(sbuf *buf, const char *fmt, ...) {
- char temp[GRPC_HTTPCLI_MAX_HEADER_LENGTH];
- size_t len;
- va_list args;
-
- va_start(args, fmt);
- len = vsprintf(temp, fmt, args);
- va_end(args);
-
- sbuf_append(buf, temp, len);
-}
-
-static void fill_common_header(const grpc_httpcli_request *request, sbuf *buf) {
+static void fill_common_header(const grpc_httpcli_request *request, gpr_strvec *buf) {
size_t i;
- sbprintf(buf, "%s HTTP/1.0\r\n", request->path);
+ gpr_strvec_add(buf, gpr_strdup(request->path));
+ gpr_strvec_add(buf, gpr_strdup(" HTTP/1.0\r\n"));
/* just in case some crazy server really expects HTTP/1.1 */
- sbprintf(buf, "Host: %s\r\n", request->host);
- sbprintf(buf, "Connection: close\r\n");
- sbprintf(buf, "User-Agent: %s\r\n", GRPC_HTTPCLI_USER_AGENT);
+ gpr_strvec_add(buf, gpr_strdup("Host: "));
+ gpr_strvec_add(buf, gpr_strdup(request->host));
+ gpr_strvec_add(buf, gpr_strdup("\r\n"));
+ gpr_strvec_add(buf, gpr_strdup("Connection: close\r\n"));
+ gpr_strvec_add(buf, gpr_strdup("User-Agent: "GRPC_HTTPCLI_USER_AGENT"\r\n"));
/* user supplied headers */
for (i = 0; i < request->hdr_count; i++) {
- sbprintf(buf, "%s: %s\r\n", request->hdrs[i].key, request->hdrs[i].value);
+ gpr_strvec_add(buf, gpr_strdup(request->hdrs[i].key));
+ gpr_strvec_add(buf, gpr_strdup(": "));
+ gpr_strvec_add(buf, gpr_strdup(request->hdrs[i].value));
+ gpr_strvec_add(buf, gpr_strdup("\r\n"));
}
}
gpr_slice grpc_httpcli_format_get_request(const grpc_httpcli_request *request) {
- sbuf out = {0, 0, NULL};
+ gpr_strvec out;
+ char *flat;
+ size_t flat_len;
- sbprintf(&out, "GET ");
+ gpr_strvec_init(&out);
+ gpr_strvec_add(&out, gpr_strdup("GET "));
fill_common_header(request, &out);
- sbprintf(&out, "\r\n");
+ gpr_strvec_add(&out, gpr_strdup("\r\n"));
- return gpr_slice_new(out.data, out.length, gpr_free);
+ flat = gpr_strvec_flatten(&out, &flat_len);
+ gpr_strvec_destroy(&out);
+
+ return gpr_slice_new(flat, flat_len, gpr_free);
}
gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request,
const char *body_bytes,
size_t body_size) {
- sbuf out = {0, 0, NULL};
+ gpr_strvec out;
+ char *tmp;
+ size_t out_len;
size_t i;
- sbprintf(&out, "POST ");
+ gpr_strvec_init(&out);
+
+ gpr_strvec_add(&out, gpr_strdup("POST "));
fill_common_header(request, &out);
if (body_bytes) {
gpr_uint8 has_content_type = 0;
@@ -108,14 +98,18 @@ gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request,
}
}
if (!has_content_type) {
- sbprintf(&out, "Content-Type: text/plain\r\n");
+ gpr_strvec_add(&out, gpr_strdup("Content-Type: text/plain\r\n"));
}
- sbprintf(&out, "Content-Length: %lu\r\n", (unsigned long)body_size);
+ gpr_asprintf(&tmp, "Content-Length: %lu\r\n", (unsigned long)body_size);
+ gpr_strvec_add(&out, tmp);
}
- sbprintf(&out, "\r\n");
+ gpr_strvec_add(&out, gpr_strdup("\r\n"));
+ tmp = gpr_strvec_flatten(&out, &out_len);
if (body_bytes) {
- sbuf_append(&out, body_bytes, body_size);
+ tmp = gpr_realloc(tmp, out_len + body_size);
+ memcpy(tmp + out_len, body_bytes, body_size);
+ out_len += body_size;
}
- return gpr_slice_new(out.data, out.length, gpr_free);
+ return gpr_slice_new(tmp, out_len, gpr_free);
}
diff --git a/src/core/security/auth.c b/src/core/security/auth.c
index f743b25838..9d0c075bc3 100644
--- a/src/core/security/auth.c
+++ b/src/core/security/auth.c
@@ -57,7 +57,7 @@ static void on_credentials_metadata(void *user_data, grpc_mdelem **md_elems,
grpc_call_element *elem = (grpc_call_element *)user_data;
size_t i;
for (i = 0; i < num_md; i++) {
- grpc_call_element_send_metadata(elem, md_elems[i]);
+ grpc_call_element_send_metadata(elem, grpc_mdelem_ref(md_elems[i]));
}
grpc_call_next_op(elem, &((call_data *)elem->call_data)->op);
}
diff --git a/src/core/support/string.c b/src/core/support/string.c
index 9b5cac7596..97bce60f94 100644
--- a/src/core/support/string.c
+++ b/src/core/support/string.c
@@ -14,7 +14,7 @@
* 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
+ * 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
@@ -152,3 +152,49 @@ int gpr_ltoa(long value, char *string) {
string[i] = 0;
return i;
}
+
+char *gpr_strjoin(const char **strs, size_t nstrs, size_t *final_length) {
+ size_t out_length = 0;
+ size_t i;
+ char *out;
+ for (i = 0; i < nstrs; i++) {
+ out_length += strlen(strs[i]);
+ }
+ out_length += 1; /* null terminator */
+ out = gpr_malloc(out_length);
+ out_length = 0;
+ for (i = 0; i < nstrs; i++) {
+ size_t slen = strlen(strs[i]);
+ memcpy(out + out_length, strs[i], slen);
+ out_length += slen;
+ }
+ out[out_length] = 0;
+ if (final_length != NULL) {
+ *final_length = out_length;
+ }
+ return out;
+}
+
+void gpr_strvec_init(gpr_strvec *sv) {
+ memset(sv, 0, sizeof(*sv));
+}
+
+void gpr_strvec_destroy(gpr_strvec *sv) {
+ size_t i;
+ for (i = 0; i < sv->count; i++) {
+ gpr_free(sv->strs[i]);
+ }
+ gpr_free(sv->strs);
+}
+
+void gpr_strvec_add(gpr_strvec *sv, char *str) {
+ if (sv->count == sv->capacity) {
+ sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2);
+ sv->strs = gpr_realloc(sv->strs, sizeof(char*) * sv->capacity);
+ }
+ sv->strs[sv->count++] = str;
+}
+
+char *gpr_strvec_flatten(gpr_strvec *sv, size_t *final_length) {
+ return gpr_strjoin((const char**)sv->strs, sv->count, final_length);
+}
diff --git a/src/core/support/string.h b/src/core/support/string.h
index 28b7029ecd..64e06d3b6a 100644
--- a/src/core/support/string.h
+++ b/src/core/support/string.h
@@ -81,6 +81,27 @@ void gpr_reverse_bytes(char *str, int len);
the result is undefined. */
int gpr_asprintf(char **strp, const char *format, ...);
+/* Join a set of strings, returning the resulting string.
+ Total combined length (excluding null terminator) is returned in total_length
+ if it is non-null. */
+char *gpr_strjoin(const char **strs, size_t nstrs, size_t *total_length);
+
+/* A vector of strings... for building up a final string one piece at a time */
+typedef struct {
+ char **strs;
+ size_t count;
+ size_t capacity;
+} gpr_strvec;
+
+/* Initialize/destroy */
+void gpr_strvec_init(gpr_strvec *strs);
+void gpr_strvec_destroy(gpr_strvec *strs);
+/* Add a string to a strvec, takes ownership of the string */
+void gpr_strvec_add(gpr_strvec *strs, char *add);
+/* Return a joined string with all added substrings, optionally setting
+ total_length as per gpr_strjoin */
+char *gpr_strvec_flatten(gpr_strvec *strs, size_t *total_length);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 52a4270faf..e088793f01 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -981,3 +981,8 @@ void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) {
call->have_alarm = 1;
grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now());
}
+
+grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) {
+ return CALL_STACK_FROM_CALL(call);
+}
+
diff --git a/src/core/surface/call.h b/src/core/surface/call.h
index 01605bb38a..804b387cb1 100644
--- a/src/core/surface/call.h
+++ b/src/core/surface/call.h
@@ -64,6 +64,8 @@ void grpc_call_client_initial_metadata_complete(
void grpc_call_set_deadline(grpc_call_element *surface_element,
gpr_timespec deadline);
+grpc_call_stack *grpc_call_get_call_stack(grpc_call *call);
+
/* Given the top call_element, get the call object. */
grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element);
diff --git a/src/core/surface/event_string.c b/src/core/surface/event_string.c
index e38ef06c9f..8975d312ee 100644
--- a/src/core/surface/event_string.c
+++ b/src/core/surface/event_string.c
@@ -38,8 +38,10 @@
#include "src/core/support/string.h"
#include <grpc/byte_buffer.h>
-static size_t addhdr(char *p, grpc_event *ev) {
- return sprintf(p, "tag:%p call:%p", ev->tag, (void *)ev->call);
+static void addhdr(gpr_strvec *buf, grpc_event *ev) {
+ char *tmp;
+ gpr_asprintf(&tmp, "tag:%p call:%p", ev->tag, (void *)ev->call);
+ gpr_strvec_add(buf, tmp);
}
static const char *errstr(grpc_op_error err) {
@@ -52,72 +54,84 @@ static const char *errstr(grpc_op_error err) {
return "UNKNOWN_UNKNOWN";
}
-static size_t adderr(char *p, grpc_op_error err) {
- return sprintf(p, " err=%s", errstr(err));
+static void adderr(gpr_strvec *buf, grpc_op_error err) {
+ char *tmp;
+ gpr_asprintf(&tmp, " err=%s", errstr(err));
+ gpr_strvec_add(buf, tmp);
}
char *grpc_event_string(grpc_event *ev) {
- char buffer[1024];
- char *p = buffer;
+ char *out;
+ char *tmp;
+ gpr_strvec buf;
if (ev == NULL) return gpr_strdup("null");
+ gpr_strvec_init(&buf);
+
switch (ev->type) {
case GRPC_SERVER_SHUTDOWN:
- p += sprintf(p, "SERVER_SHUTDOWN");
+ gpr_strvec_add(&buf, gpr_strdup("SERVER_SHUTDOWN"));
break;
case GRPC_QUEUE_SHUTDOWN:
- p += sprintf(p, "QUEUE_SHUTDOWN");
+ gpr_strvec_add(&buf, gpr_strdup("QUEUE_SHUTDOWN"));
break;
case GRPC_READ:
- p += sprintf(p, "READ: ");
- p += addhdr(p, ev);
+ gpr_strvec_add(&buf, gpr_strdup("READ: "));
+ addhdr(&buf, ev);
if (ev->data.read) {
- p += sprintf(p, " %d bytes",
+ gpr_asprintf(&tmp, " %d bytes",
(int)grpc_byte_buffer_length(ev->data.read));
+ gpr_strvec_add(&buf, tmp);
} else {
- p += sprintf(p, " end-of-stream");
+ gpr_strvec_add(&buf, gpr_strdup(" end-of-stream"));
}
break;
case GRPC_INVOKE_ACCEPTED:
- p += sprintf(p, "INVOKE_ACCEPTED: ");
- p += addhdr(p, ev);
- p += adderr(p, ev->data.invoke_accepted);
+ gpr_strvec_add(&buf, gpr_strdup("INVOKE_ACCEPTED: "));
+ addhdr(&buf, ev);
+ adderr(&buf, ev->data.invoke_accepted);
break;
case GRPC_WRITE_ACCEPTED:
- p += sprintf(p, "WRITE_ACCEPTED: ");
- p += addhdr(p, ev);
- p += adderr(p, ev->data.write_accepted);
+ gpr_strvec_add(&buf, gpr_strdup("WRITE_ACCEPTED: "));
+ addhdr(&buf, ev);
+ adderr(&buf, ev->data.write_accepted);
break;
case GRPC_FINISH_ACCEPTED:
- p += sprintf(p, "FINISH_ACCEPTED: ");
- p += addhdr(p, ev);
- p += adderr(p, ev->data.write_accepted);
+ gpr_strvec_add(&buf, gpr_strdup("FINISH_ACCEPTED: "));
+ addhdr(&buf, ev);
+ adderr(&buf, ev->data.write_accepted);
break;
case GRPC_CLIENT_METADATA_READ:
- p += sprintf(p, "CLIENT_METADATA_READ: ");
- p += addhdr(p, ev);
- p += sprintf(p, " %d elements", (int)ev->data.client_metadata_read.count);
+ gpr_strvec_add(&buf, gpr_strdup("CLIENT_METADATA_READ: "));
+ addhdr(&buf, ev);
+ gpr_asprintf(&tmp, " %d elements",
+ (int)ev->data.client_metadata_read.count);
+ gpr_strvec_add(&buf, tmp);
break;
case GRPC_FINISHED:
- p += sprintf(p, "FINISHED: ");
- p += addhdr(p, ev);
- p += sprintf(p, " status=%d details='%s' %d metadata elements",
+ gpr_strvec_add(&buf, gpr_strdup("FINISHED: "));
+ addhdr(&buf, ev);
+ gpr_asprintf(&tmp, " status=%d details='%s' %d metadata elements",
ev->data.finished.status, ev->data.finished.details,
(int)ev->data.finished.metadata_count);
+ gpr_strvec_add(&buf, tmp);
break;
case GRPC_SERVER_RPC_NEW:
- p += sprintf(p, "SERVER_RPC_NEW: ");
- p += addhdr(p, ev);
- p += sprintf(p, " method='%s' host='%s' %d metadata elements",
+ gpr_strvec_add(&buf, gpr_strdup("SERVER_RPC_NEW: "));
+ addhdr(&buf, ev);
+ gpr_asprintf(&tmp, " method='%s' host='%s' %d metadata elements",
ev->data.server_rpc_new.method, ev->data.server_rpc_new.host,
(int)ev->data.server_rpc_new.metadata_count);
+ gpr_strvec_add(&buf, tmp);
break;
case GRPC_COMPLETION_DO_NOT_USE:
- p += sprintf(p, "DO_NOT_USE (this is a bug)");
- p += addhdr(p, ev);
+ gpr_strvec_add(&buf, gpr_strdup("DO_NOT_USE (this is a bug)"));
+ addhdr(&buf, ev);
break;
}
- return gpr_strdup(buffer);
+ out = gpr_strvec_flatten(&buf, NULL);
+ gpr_strvec_destroy(&buf);
+ return out;
}
diff --git a/src/node/binding.gyp b/src/node/binding.gyp
index fe4b5da9c8..cf2a6acb04 100644
--- a/src/node/binding.gyp
+++ b/src/node/binding.gyp
@@ -28,17 +28,17 @@
},
"target_name": "grpc",
"sources": [
- "byte_buffer.cc",
- "call.cc",
- "channel.cc",
- "completion_queue_async_worker.cc",
- "credentials.cc",
- "event.cc",
- "node_grpc.cc",
- "server.cc",
- "server_credentials.cc",
- "tag.cc",
- "timeval.cc"
+ "ext/byte_buffer.cc",
+ "ext/call.cc",
+ "ext/channel.cc",
+ "ext/completion_queue_async_worker.cc",
+ "ext/credentials.cc",
+ "ext/event.cc",
+ "ext/node_grpc.cc",
+ "ext/server.cc",
+ "ext/server_credentials.cc",
+ "ext/tag.cc",
+ "ext/timeval.cc"
],
'conditions' : [
['no_install=="yes"', {
diff --git a/src/node/examples/math_server.js b/src/node/examples/math_server.js
index d649b4fd6d..e65cfe3002 100644
--- a/src/node/examples/math_server.js
+++ b/src/node/examples/math_server.js
@@ -52,7 +52,8 @@ var Server = grpc.buildServer([math.Math.service]);
*/
function mathDiv(call, cb) {
var req = call.request;
- if (req.divisor == 0) {
+ // Unary + is explicit coersion to integer
+ if (+req.divisor === 0) {
cb(new Error('cannot divide by zero'));
}
cb(null, {
@@ -89,7 +90,7 @@ function mathSum(call, cb) {
// Here, call is a standard readable Node object Stream
var sum = 0;
call.on('data', function(data) {
- sum += data.num | 0;
+ sum += (+data.num);
});
call.on('end', function() {
cb(null, {num: sum});
@@ -104,7 +105,7 @@ function mathDivMany(stream) {
Transform.call(this, options);
}
DivTransform.prototype._transform = function(div_args, encoding, callback) {
- if (div_args.divisor == 0) {
+ if (+div_args.divisor === 0) {
callback(new Error('cannot divide by zero'));
}
callback(null, {
diff --git a/src/node/byte_buffer.cc b/src/node/ext/byte_buffer.cc
index 142951475a..142951475a 100644
--- a/src/node/byte_buffer.cc
+++ b/src/node/ext/byte_buffer.cc
diff --git a/src/node/byte_buffer.h b/src/node/ext/byte_buffer.h
index ee2b4c0d15..ee2b4c0d15 100644
--- a/src/node/byte_buffer.h
+++ b/src/node/ext/byte_buffer.h
diff --git a/src/node/call.cc b/src/node/ext/call.cc
index 6434c2f0d5..6434c2f0d5 100644
--- a/src/node/call.cc
+++ b/src/node/ext/call.cc
diff --git a/src/node/call.h b/src/node/ext/call.h
index 1924a1bf42..1924a1bf42 100644
--- a/src/node/call.h
+++ b/src/node/ext/call.h
diff --git a/src/node/channel.cc b/src/node/ext/channel.cc
index 9087d6f919..9087d6f919 100644
--- a/src/node/channel.cc
+++ b/src/node/ext/channel.cc
diff --git a/src/node/channel.h b/src/node/ext/channel.h
index 140cbf201a..140cbf201a 100644
--- a/src/node/channel.h
+++ b/src/node/ext/channel.h
diff --git a/src/node/completion_queue_async_worker.cc b/src/node/ext/completion_queue_async_worker.cc
index 8de7db66d5..8de7db66d5 100644
--- a/src/node/completion_queue_async_worker.cc
+++ b/src/node/ext/completion_queue_async_worker.cc
diff --git a/src/node/completion_queue_async_worker.h b/src/node/ext/completion_queue_async_worker.h
index 2c928b7024..2c928b7024 100644
--- a/src/node/completion_queue_async_worker.h
+++ b/src/node/ext/completion_queue_async_worker.h
diff --git a/src/node/credentials.cc b/src/node/ext/credentials.cc
index c8859ed941..c8859ed941 100644
--- a/src/node/credentials.cc
+++ b/src/node/ext/credentials.cc
diff --git a/src/node/credentials.h b/src/node/ext/credentials.h
index 981e5a99bc..981e5a99bc 100644
--- a/src/node/credentials.h
+++ b/src/node/ext/credentials.h
diff --git a/src/node/event.cc b/src/node/ext/event.cc
index 2ca38b7448..2ca38b7448 100644
--- a/src/node/event.cc
+++ b/src/node/ext/event.cc
diff --git a/src/node/event.h b/src/node/ext/event.h
index e06d8f0168..e06d8f0168 100644
--- a/src/node/event.h
+++ b/src/node/ext/event.h
diff --git a/src/node/node_grpc.cc b/src/node/ext/node_grpc.cc
index bc1dfaf899..bc1dfaf899 100644
--- a/src/node/node_grpc.cc
+++ b/src/node/ext/node_grpc.cc
diff --git a/src/node/server.cc b/src/node/ext/server.cc
index b102775d33..b102775d33 100644
--- a/src/node/server.cc
+++ b/src/node/ext/server.cc
diff --git a/src/node/server.h b/src/node/ext/server.h
index d50f1fb6c5..d50f1fb6c5 100644
--- a/src/node/server.h
+++ b/src/node/ext/server.h
diff --git a/src/node/server_credentials.cc b/src/node/ext/server_credentials.cc
index 393f3a6305..393f3a6305 100644
--- a/src/node/server_credentials.cc
+++ b/src/node/ext/server_credentials.cc
diff --git a/src/node/server_credentials.h b/src/node/ext/server_credentials.h
index 8baae3f185..8baae3f185 100644
--- a/src/node/server_credentials.h
+++ b/src/node/ext/server_credentials.h
diff --git a/src/node/tag.cc b/src/node/ext/tag.cc
index dc8e523e12..dc8e523e12 100644
--- a/src/node/tag.cc
+++ b/src/node/ext/tag.cc
diff --git a/src/node/tag.h b/src/node/ext/tag.h
index bdb09252d9..bdb09252d9 100644
--- a/src/node/tag.h
+++ b/src/node/ext/tag.h
diff --git a/src/node/timeval.cc b/src/node/ext/timeval.cc
index 687e33576b..687e33576b 100644
--- a/src/node/timeval.cc
+++ b/src/node/ext/timeval.cc
diff --git a/src/node/timeval.h b/src/node/ext/timeval.h
index 1fb0f2c690..1fb0f2c690 100644
--- a/src/node/timeval.h
+++ b/src/node/ext/timeval.h
diff --git a/src/node/main.js b/src/node/index.js
index 751c3525d3..0627e7f557 100644
--- a/src/node/main.js
+++ b/src/node/index.js
@@ -35,9 +35,9 @@ var _ = require('underscore');
var ProtoBuf = require('protobufjs');
-var surface_client = require('./surface_client.js');
+var surface_client = require('./src/surface_client.js');
-var surface_server = require('./surface_server.js');
+var surface_server = require('./src/surface_server.js');
var grpc = require('bindings')('grpc');
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index cf75b9a77a..9306317b68 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -183,7 +183,7 @@ function pingPong(client, done) {
assert.equal(response.payload.body.limit - response.payload.body.offset,
response_sizes[index]);
index += 1;
- if (index == 4) {
+ if (index === 4) {
call.end();
} else {
call.write({
diff --git a/src/node/package.json b/src/node/package.json
index 5f3c6fa345..8a0b51dda8 100644
--- a/src/node/package.json
+++ b/src/node/package.json
@@ -17,5 +17,5 @@
"mocha": "~1.21.0",
"minimist": "^1.1.0"
},
- "main": "main.js"
+ "main": "index.js"
}
diff --git a/src/node/client.js b/src/node/src/client.js
index 2fefd14bbc..3a1c9eef84 100644
--- a/src/node/client.js
+++ b/src/node/src/client.js
@@ -105,7 +105,7 @@ function GrpcClientStream(call, serialize, deserialize) {
return;
}
var data = event.data;
- if (self.push(data) && data != null) {
+ if (self.push(self.deserialize(data)) && data != null) {
self._call.startRead(readCallback);
} else {
reading = false;
@@ -155,12 +155,20 @@ GrpcClientStream.prototype._read = function(size) {
*/
GrpcClientStream.prototype._write = function(chunk, encoding, callback) {
var self = this;
- self._call.startWrite(chunk, function(event) {
+ self._call.startWrite(self.serialize(chunk), function(event) {
callback();
}, 0);
};
/**
+ * Cancel the ongoing call. If the call has not already finished, it will finish
+ * with status CANCELLED.
+ */
+GrpcClientStream.prototype.cancel = function() {
+ this._call.cancel();
+};
+
+/**
* Make a request on the channel to the given method with the given arguments
* @param {grpc.Channel} channel The channel on which to make the request
* @param {string} method The method to request
@@ -185,7 +193,7 @@ function makeRequest(channel,
if (metadata) {
call.addMetadata(metadata);
}
- return new GrpcClientStream(call);
+ return new GrpcClientStream(call, serialize, deserialize);
}
/**
diff --git a/src/node/common.js b/src/node/src/common.js
index 54247e3fa1..54247e3fa1 100644
--- a/src/node/common.js
+++ b/src/node/src/common.js
diff --git a/src/node/server.js b/src/node/src/server.js
index eca20aa5fd..03cdbe6f98 100644
--- a/src/node/server.js
+++ b/src/node/src/server.js
@@ -151,7 +151,7 @@ function GrpcServerStream(call, serialize, deserialize) {
return;
}
var data = event.data;
- if (self.push(deserialize(data)) && data != null) {
+ if (self.push(self.deserialize(data)) && data != null) {
self._call.startRead(readCallback);
} else {
reading = false;
@@ -233,7 +233,7 @@ function Server(options) {
function handleNewCall(event) {
var call = event.call;
var data = event.data;
- if (data == null) {
+ if (data === null) {
return;
}
server.requestCall(handleNewCall);
@@ -246,6 +246,7 @@ function Server(options) {
call.serverAccept(function(event) {
if (event.data.code === grpc.status.CANCELLED) {
cancelled = true;
+ stream.emit('cancelled');
}
}, 0);
call.serverEndInitialMetadata(0);
diff --git a/src/node/surface_client.js b/src/node/src/surface_client.js
index 996e3d101f..16c31809f4 100644
--- a/src/node/surface_client.js
+++ b/src/node/src/surface_client.js
@@ -63,114 +63,80 @@ util.inherits(ClientReadableObjectStream, Readable);
* client side. Extends from stream.Readable.
* @constructor
* @param {stream} stream Underlying binary Duplex stream for the call
- * @param {function(Buffer)} deserialize Function for deserializing binary data
- * @param {object} options Stream options
*/
-function ClientReadableObjectStream(stream, deserialize, options) {
- options = _.extend(options, {objectMode: true});
+function ClientReadableObjectStream(stream) {
+ var options = {objectMode: true};
Readable.call(this, options);
this._stream = stream;
var self = this;
forwardEvent(stream, this, 'status');
forwardEvent(stream, this, 'metadata');
this._stream.on('data', function forwardData(chunk) {
- if (!self.push(deserialize(chunk))) {
+ if (!self.push(chunk)) {
self._stream.pause();
}
});
this._stream.pause();
}
-util.inherits(ClientWritableObjectStream, Writable);
-
/**
- * Class for representing a gRPC client streaming call as a Node stream on the
- * client side. Extends from stream.Writable.
- * @constructor
- * @param {stream} stream Underlying binary Duplex stream for the call
- * @param {function(*):Buffer} serialize Function for serializing objects
- * @param {object} options Stream options
+ * _read implementation for both types of streams that allow reading.
+ * @this {ClientReadableObjectStream}
+ * @param {number} size Ignored
*/
-function ClientWritableObjectStream(stream, serialize, options) {
- options = _.extend(options, {objectMode: true});
- Writable.call(this, options);
- this._stream = stream;
- this._serialize = serialize;
- forwardEvent(stream, this, 'status');
- forwardEvent(stream, this, 'metadata');
- this.on('finish', function() {
- this._stream.end();
- });
+function _read(size) {
+ this._stream.resume();
}
+/**
+ * See docs for _read
+ */
+ClientReadableObjectStream.prototype._read = _read;
-util.inherits(ClientBidiObjectStream, Duplex);
+util.inherits(ClientWritableObjectStream, Writable);
/**
- * Class for representing a gRPC bidi streaming call as a Node stream on the
- * client side. Extends from stream.Duplex.
+ * Class for representing a gRPC client streaming call as a Node stream on the
+ * client side. Extends from stream.Writable.
* @constructor
* @param {stream} stream Underlying binary Duplex stream for the call
- * @param {function(*):Buffer} serialize Function for serializing objects
- * @param {function(Buffer)} deserialize Function for deserializing binary data
- * @param {object} options Stream options
*/
-function ClientBidiObjectStream(stream, serialize, deserialize, options) {
- options = _.extend(options, {objectMode: true});
- Duplex.call(this, options);
+function ClientWritableObjectStream(stream) {
+ var options = {objectMode: true};
+ Writable.call(this, options);
this._stream = stream;
- this._serialize = serialize;
- var self = this;
forwardEvent(stream, this, 'status');
forwardEvent(stream, this, 'metadata');
- this._stream.on('data', function forwardData(chunk) {
- if (!self.push(deserialize(chunk))) {
- self._stream.pause();
- }
- });
- this._stream.pause();
this.on('finish', function() {
this._stream.end();
});
}
/**
- * _read implementation for both types of streams that allow reading.
- * @this {ClientReadableObjectStream|ClientBidiObjectStream}
- * @param {number} size Ignored
- */
-function _read(size) {
- this._stream.resume();
-}
-
-/**
- * See docs for _read
- */
-ClientReadableObjectStream.prototype._read = _read;
-/**
- * See docs for _read
- */
-ClientBidiObjectStream.prototype._read = _read;
-
-/**
* _write implementation for both types of streams that allow writing
- * @this {ClientWritableObjectStream|ClientBidiObjectStream}
+ * @this {ClientWritableObjectStream}
* @param {*} chunk The value to write to the stream
* @param {string} encoding Ignored
* @param {function(Error)} callback Callback to call when finished writing
*/
function _write(chunk, encoding, callback) {
- this._stream.write(this._serialize(chunk), encoding, callback);
+ this._stream.write(chunk, encoding, callback);
}
/**
* See docs for _write
*/
ClientWritableObjectStream.prototype._write = _write;
+
/**
- * See docs for _write
+ * Cancel the underlying call
*/
-ClientBidiObjectStream.prototype._write = _write;
+function cancel() {
+ this._stream.cancel();
+}
+
+ClientReadableObjectStream.prototype.cancel = cancel;
+ClientWritableObjectStream.prototype.cancel = cancel;
/**
* Get a function that can make unary requests to the specified method.
@@ -196,19 +162,28 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
* @return {EventEmitter} An event emitter for stream related events
*/
function makeUnaryRequest(argument, callback, metadata, deadline) {
- var stream = client.makeRequest(this.channel, method, metadata, deadline);
+ var stream = client.makeRequest(this.channel, method, serialize,
+ deserialize, metadata, deadline);
var emitter = new EventEmitter();
+ emitter.cancel = function cancel() {
+ stream.cancel();
+ };
forwardEvent(stream, emitter, 'status');
forwardEvent(stream, emitter, 'metadata');
- stream.write(serialize(argument));
+ stream.write(argument);
stream.end();
stream.on('data', function forwardData(chunk) {
try {
- callback(null, deserialize(chunk));
+ callback(null, chunk);
} catch (e) {
callback(e);
}
});
+ stream.on('status', function forwardStatus(status) {
+ if (status.code !== client.status.OK) {
+ callback(status);
+ }
+ });
return emitter;
}
return makeUnaryRequest;
@@ -236,15 +211,21 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
* @return {EventEmitter} An event emitter for stream related events
*/
function makeClientStreamRequest(callback, metadata, deadline) {
- var stream = client.makeRequest(this.channel, method, metadata, deadline);
- var obj_stream = new ClientWritableObjectStream(stream, serialize, {});
+ var stream = client.makeRequest(this.channel, method, serialize,
+ deserialize, metadata, deadline);
+ var obj_stream = new ClientWritableObjectStream(stream);
stream.on('data', function forwardData(chunk) {
try {
- callback(null, deserialize(chunk));
+ callback(null, chunk);
} catch (e) {
callback(e);
}
});
+ stream.on('status', function forwardStatus(status) {
+ if (status.code !== client.status.OK) {
+ callback(status);
+ }
+ });
return obj_stream;
}
return makeClientStreamRequest;
@@ -272,9 +253,10 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
* @return {EventEmitter} An event emitter for stream related events
*/
function makeServerStreamRequest(argument, metadata, deadline) {
- var stream = client.makeRequest(this.channel, method, metadata, deadline);
- var obj_stream = new ClientReadableObjectStream(stream, deserialize, {});
- stream.write(serialize(argument));
+ var stream = client.makeRequest(this.channel, method, serialize,
+ deserialize, metadata, deadline);
+ var obj_stream = new ClientReadableObjectStream(stream);
+ stream.write(argument);
stream.end();
return obj_stream;
}
@@ -301,12 +283,8 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
* @return {EventEmitter} An event emitter for stream related events
*/
function makeBidiStreamRequest(metadata, deadline) {
- var stream = client.makeRequest(this.channel, method, metadata, deadline);
- var obj_stream = new ClientBidiObjectStream(stream,
- serialize,
- deserialize,
- {});
- return obj_stream;
+ return client.makeRequest(this.channel, method, serialize,
+ deserialize, metadata, deadline);
}
return makeBidiStreamRequest;
}
diff --git a/src/node/surface_server.js b/src/node/src/surface_server.js
index bc688839fe..af23ec211c 100644
--- a/src/node/surface_server.js
+++ b/src/node/src/surface_server.js
@@ -54,67 +54,20 @@ util.inherits(ServerReadableObjectStream, Readable);
* server side. Extends from stream.Readable.
* @constructor
* @param {stream} stream Underlying binary Duplex stream for the call
- * @param {function(Buffer)} deserialize Function for deserializing binary data
- * @param {object} options Stream options
*/
-function ServerReadableObjectStream(stream, deserialize, options) {
- options = _.extend(options, {objectMode: true});
+function ServerReadableObjectStream(stream) {
+ var options = {objectMode: true};
Readable.call(this, options);
this._stream = stream;
Object.defineProperty(this, 'cancelled', {
get: function() { return stream.cancelled; }
});
var self = this;
- this._stream.on('data', function forwardData(chunk) {
- if (!self.push(deserialize(chunk))) {
- self._stream.pause();
- }
- });
- this._stream.on('end', function forwardEnd() {
- self.push(null);
+ this._stream.on('cancelled', function() {
+ self.emit('cancelled');
});
- this._stream.pause();
-}
-
-util.inherits(ServerWritableObjectStream, Writable);
-
-/**
- * Class for representing a gRPC server streaming call as a Node stream on the
- * server side. Extends from stream.Writable.
- * @constructor
- * @param {stream} stream Underlying binary Duplex stream for the call
- * @param {function(*):Buffer} serialize Function for serializing objects
- * @param {object} options Stream options
- */
-function ServerWritableObjectStream(stream, serialize, options) {
- options = _.extend(options, {objectMode: true});
- Writable.call(this, options);
- this._stream = stream;
- this._serialize = serialize;
- this.on('finish', function() {
- this._stream.end();
- });
-}
-
-util.inherits(ServerBidiObjectStream, Duplex);
-
-/**
- * Class for representing a gRPC bidi streaming call as a Node stream on the
- * server side. Extends from stream.Duplex.
- * @constructor
- * @param {stream} stream Underlying binary Duplex stream for the call
- * @param {function(*):Buffer} serialize Function for serializing objects
- * @param {function(Buffer)} deserialize Function for deserializing binary data
- * @param {object} options Stream options
- */
-function ServerBidiObjectStream(stream, serialize, deserialize, options) {
- options = _.extend(options, {objectMode: true});
- Duplex.call(this, options);
- this._stream = stream;
- this._serialize = serialize;
- var self = this;
this._stream.on('data', function forwardData(chunk) {
- if (!self.push(deserialize(chunk))) {
+ if (!self.push(chunk)) {
self._stream.pause();
}
});
@@ -122,9 +75,6 @@ function ServerBidiObjectStream(stream, serialize, deserialize, options) {
self.push(null);
});
this._stream.pause();
- this.on('finish', function() {
- this._stream.end();
- });
}
/**
@@ -140,39 +90,49 @@ function _read(size) {
* See docs for _read
*/
ServerReadableObjectStream.prototype._read = _read;
+
+util.inherits(ServerWritableObjectStream, Writable);
+
/**
- * See docs for _read
+ * Class for representing a gRPC server streaming call as a Node stream on the
+ * server side. Extends from stream.Writable.
+ * @constructor
+ * @param {stream} stream Underlying binary Duplex stream for the call
*/
-ServerBidiObjectStream.prototype._read = _read;
+function ServerWritableObjectStream(stream) {
+ var options = {objectMode: true};
+ Writable.call(this, options);
+ this._stream = stream;
+ this._stream.on('cancelled', function() {
+ self.emit('cancelled');
+ });
+ this.on('finish', function() {
+ this._stream.end();
+ });
+}
/**
* _write implementation for both types of streams that allow writing
- * @this {ServerWritableObjectStream|ServerBidiObjectStream}
+ * @this {ServerWritableObjectStream}
* @param {*} chunk The value to write to the stream
* @param {string} encoding Ignored
* @param {function(Error)} callback Callback to call when finished writing
*/
function _write(chunk, encoding, callback) {
- this._stream.write(this._serialize(chunk), encoding, callback);
+ this._stream.write(chunk, encoding, callback);
}
/**
* See docs for _write
*/
ServerWritableObjectStream.prototype._write = _write;
-/**
- * See docs for _write
- */
-ServerBidiObjectStream.prototype._write = _write;
/**
* Creates a binary stream handler function from a unary handler function
* @param {function(Object, function(Error, *))} handler Unary call handler
- * @param {function(*):Buffer} serialize Serialization function
- * @param {function(Buffer):*} deserialize Deserialization function
* @return {function(stream)} Binary stream handler
*/
-function makeUnaryHandler(handler, serialize, deserialize) {
+function makeUnaryHandler(handler) {
/**
* Handles a stream by reading a single data value, passing it to the handler,
* and writing the response back to the stream.
@@ -180,15 +140,18 @@ function makeUnaryHandler(handler, serialize, deserialize) {
*/
return function handleUnaryCall(stream) {
stream.on('data', function handleUnaryData(value) {
- var call = {request: deserialize(value)};
+ var call = {request: value};
Object.defineProperty(call, 'cancelled', {
get: function() { return stream.cancelled;}
});
+ stream.on('cancelled', function() {
+ call.emit('cancelled');
+ });
handler(call, function sendUnaryData(err, value) {
if (err) {
stream.emit('error', err);
} else {
- stream.write(serialize(value));
+ stream.write(value);
stream.end();
}
});
@@ -201,23 +164,21 @@ function makeUnaryHandler(handler, serialize, deserialize) {
* function
* @param {function(Readable, function(Error, *))} handler Client stream call
* handler
- * @param {function(*):Buffer} serialize Serialization function
- * @param {function(Buffer):*} deserialize Deserialization function
* @return {function(stream)} Binary stream handler
*/
-function makeClientStreamHandler(handler, serialize, deserialize) {
+function makeClientStreamHandler(handler) {
/**
* Handles a stream by passing a deserializing stream to the handler and
* writing the response back to the stream.
* @param {stream} stream Binary data stream
*/
return function handleClientStreamCall(stream) {
- var object_stream = new ServerReadableObjectStream(stream, deserialize, {});
+ var object_stream = new ServerReadableObjectStream(stream);
handler(object_stream, function sendClientStreamData(err, value) {
if (err) {
stream.emit('error', err);
} else {
- stream.write(serialize(value));
+ stream.write(value);
stream.end();
}
});
@@ -228,11 +189,9 @@ function makeClientStreamHandler(handler, serialize, deserialize) {
* Creates a binary stream handler function from a server stream handler
* function
* @param {function(Writable)} handler Server stream call handler
- * @param {function(*):Buffer} serialize Serialization function
- * @param {function(Buffer):*} deserialize Deserialization function
* @return {function(stream)} Binary stream handler
*/
-function makeServerStreamHandler(handler, serialize, deserialize) {
+function makeServerStreamHandler(handler) {
/**
* Handles a stream by attaching it to a serializing stream, and passing it to
* the handler.
@@ -240,10 +199,8 @@ function makeServerStreamHandler(handler, serialize, deserialize) {
*/
return function handleServerStreamCall(stream) {
stream.on('data', function handleClientData(value) {
- var object_stream = new ServerWritableObjectStream(stream,
- serialize,
- {});
- object_stream.request = deserialize(value);
+ var object_stream = new ServerWritableObjectStream(stream);
+ object_stream.request = value;
handler(object_stream);
});
};
@@ -252,23 +209,10 @@ function makeServerStreamHandler(handler, serialize, deserialize) {
/**
* Creates a binary stream handler function from a bidi stream handler function
* @param {function(Duplex)} handler Unary call handler
- * @param {function(*):Buffer} serialize Serialization function
- * @param {function(Buffer):*} deserialize Deserialization function
* @return {function(stream)} Binary stream handler
*/
-function makeBidiStreamHandler(handler, serialize, deserialize) {
- /**
- * Handles a stream by wrapping it in a serializing and deserializing object
- * stream, and passing it to the handler.
- * @param {stream} stream Binary data stream
- */
- return function handleBidiStreamCall(stream) {
- var object_stream = new ServerBidiObjectStream(stream,
- serialize,
- deserialize,
- {});
- handler(object_stream);
- };
+function makeBidiStreamHandler(handler) {
+ return handler;
}
/**
@@ -341,10 +285,13 @@ function makeServerConstructor(services) {
common.fullyQualifiedName(method) + ' not provided.');
}
var binary_handler = handler_makers[method_type](
- service_handlers[service_name][decapitalize(method.name)],
- common.serializeCls(method.resolvedResponseType.build()),
- common.deserializeCls(method.resolvedRequestType.build()));
- server.register(prefix + capitalize(method.name), binary_handler);
+ service_handlers[service_name][decapitalize(method.name)]);
+ var serialize = common.serializeCls(
+ method.resolvedResponseType.build());
+ var deserialize = common.deserializeCls(
+ method.resolvedRequestType.build());
+ server.register(prefix + capitalize(method.name), binary_handler,
+ serialize, deserialize);
});
}, this);
}
diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js
index 6e52ec89bd..b37c44abaf 100644
--- a/src/node/test/call_test.js
+++ b/src/node/test/call_test.js
@@ -34,8 +34,6 @@
var assert = require('assert');
var grpc = require('bindings')('grpc.node');
-var channel = new grpc.Channel('localhost:7070');
-
/**
* Helper function to return an absolute deadline given a relative timeout in
* seconds.
@@ -49,6 +47,17 @@ function getDeadline(timeout_secs) {
}
describe('call', function() {
+ var channel;
+ var server;
+ before(function() {
+ server = new grpc.Server();
+ var port = server.addHttp2Port('localhost:0');
+ server.start();
+ channel = new grpc.Channel('localhost:' + port);
+ });
+ after(function() {
+ server.shutdown();
+ });
describe('constructor', function() {
it('should reject anything less than 3 arguments', function() {
assert.throws(function() {
diff --git a/src/node/test/client_server_test.js b/src/node/test/client_server_test.js
index 2a25908684..d657ef41a4 100644
--- a/src/node/test/client_server_test.js
+++ b/src/node/test/client_server_test.js
@@ -35,9 +35,9 @@ var assert = require('assert');
var fs = require('fs');
var path = require('path');
var grpc = require('bindings')('grpc.node');
-var Server = require('../server');
-var client = require('../client');
-var common = require('../common');
+var Server = require('../src/server');
+var client = require('../src/client');
+var common = require('../src/common');
var _ = require('highland');
var ca_path = path.join(__dirname, 'data/ca.pem');
@@ -77,15 +77,32 @@ function errorHandler(stream) {
};
}
+/**
+ * Wait for a cancellation instead of responding
+ * @param {Stream} stream
+ */
+function cancelHandler(stream) {
+ // do nothing
+}
+
describe('echo client', function() {
- it('should receive echo responses', function(done) {
- var server = new Server();
+ var server;
+ var channel;
+ before(function() {
+ server = new Server();
var port_num = server.bind('0.0.0.0:0');
server.register('echo', echoHandler);
+ server.register('error', errorHandler);
+ server.register('cancellation', cancelHandler);
server.start();
+ channel = new grpc.Channel('localhost:' + port_num);
+ });
+ after(function() {
+ server.shutdown();
+ });
+ it('should receive echo responses', function(done) {
var messages = ['echo1', 'echo2', 'echo3', 'echo4'];
- var channel = new grpc.Channel('localhost:' + port_num);
var stream = client.makeRequest(
channel,
'echo');
@@ -98,17 +115,10 @@ describe('echo client', function() {
index += 1;
});
stream.on('end', function() {
- server.shutdown();
done();
});
});
it('should get an error status that the server throws', function(done) {
- var server = new Server();
- var port_num = server.bind('0.0.0.0:0');
- server.register('error', errorHandler);
- server.start();
-
- var channel = new grpc.Channel('localhost:' + port_num);
var stream = client.makeRequest(
channel,
'error',
@@ -121,7 +131,19 @@ describe('echo client', function() {
stream.on('status', function(status) {
assert.equal(status.code, grpc.status.UNIMPLEMENTED);
assert.equal(status.details, 'error details');
- server.shutdown();
+ done();
+ });
+ });
+ it('should be able to cancel a call', function(done) {
+ var stream = client.makeRequest(
+ channel,
+ 'cancellation',
+ null,
+ getDeadline(1));
+
+ stream.cancel();
+ stream.on('status', function(status) {
+ assert.equal(status.code, grpc.status.CANCELLED);
done();
});
});
@@ -129,7 +151,9 @@ describe('echo client', function() {
/* TODO(mlumish): explore options for reducing duplication between this test
* and the insecure echo client test */
describe('secure echo client', function() {
- it('should recieve echo responses', function(done) {
+ var server;
+ var channel;
+ before(function(done) {
fs.readFile(ca_path, function(err, ca_data) {
assert.ifError(err);
fs.readFile(key_path, function(err, key_data) {
@@ -141,34 +165,40 @@ describe('secure echo client', function() {
key_data,
pem_data);
- var server = new Server({'credentials' : server_creds});
+ server = new Server({'credentials' : server_creds});
var port_num = server.bind('0.0.0.0:0', true);
server.register('echo', echoHandler);
server.start();
- var messages = ['echo1', 'echo2', 'echo3', 'echo4'];
- var channel = new grpc.Channel('localhost:' + port_num, {
+ channel = new grpc.Channel('localhost:' + port_num, {
'grpc.ssl_target_name_override' : 'foo.test.google.com',
'credentials' : creds
});
- var stream = client.makeRequest(
- channel,
- 'echo');
-
- _(messages).map(function(val) {
- return new Buffer(val);
- }).pipe(stream);
- var index = 0;
- stream.on('data', function(chunk) {
- assert.equal(messages[index], chunk.toString());
- index += 1;
- });
- stream.on('end', function() {
- server.shutdown();
- done();
- });
+ done();
});
});
});
});
+ after(function() {
+ server.shutdown();
+ });
+ it('should recieve echo responses', function(done) {
+ var messages = ['echo1', 'echo2', 'echo3', 'echo4'];
+ var stream = client.makeRequest(
+ channel,
+ 'echo');
+
+ _(messages).map(function(val) {
+ return new Buffer(val);
+ }).pipe(stream);
+ var index = 0;
+ stream.on('data', function(chunk) {
+ assert.equal(messages[index], chunk.toString());
+ index += 1;
+ });
+ stream.on('end', function() {
+ server.shutdown();
+ done();
+ });
+ });
});
diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js
index f7ccbcf5f2..f8cb660d2d 100644
--- a/src/node/test/end_to_end_test.js
+++ b/src/node/test/end_to_end_test.js
@@ -56,14 +56,21 @@ function multiDone(done, count) {
}
describe('end-to-end', function() {
+ var server;
+ var channel;
+ before(function() {
+ server = new grpc.Server();
+ var port_num = server.addHttp2Port('0.0.0.0:0');
+ server.start();
+ channel = new grpc.Channel('localhost:' + port_num);
+ });
+ after(function() {
+ server.shutdown();
+ });
it('should start and end a request without error', function(complete) {
- var server = new grpc.Server();
var done = multiDone(function() {
complete();
- server.shutdown();
}, 2);
- var port_num = server.addHttp2Port('0.0.0.0:0');
- var channel = new grpc.Channel('localhost:' + port_num);
var deadline = new Date();
deadline.setSeconds(deadline.getSeconds() + 3);
var status_text = 'xyz';
@@ -81,7 +88,6 @@ describe('end-to-end', function() {
done();
}, 0);
- server.start();
server.requestCall(function(event) {
assert.strictEqual(event.type, grpc.completionType.SERVER_RPC_NEW);
var server_call = event.call;
@@ -109,13 +115,10 @@ describe('end-to-end', function() {
it('should send and receive data without error', function(complete) {
var req_text = 'client_request';
var reply_text = 'server_response';
- var server = new grpc.Server();
var done = multiDone(function() {
complete();
server.shutdown();
}, 6);
- var port_num = server.addHttp2Port('0.0.0.0:0');
- var channel = new grpc.Channel('localhost:' + port_num);
var deadline = new Date();
deadline.setSeconds(deadline.getSeconds() + 3);
var status_text = 'success';
@@ -151,8 +154,6 @@ describe('end-to-end', function() {
assert.strictEqual(event.data.toString(), reply_text);
done();
});
-
- server.start();
server.requestCall(function(event) {
assert.strictEqual(event.type, grpc.completionType.SERVER_RPC_NEW);
var server_call = event.call;
diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js
index 3c062b9788..6cc7d444cd 100644
--- a/src/node/test/interop_sanity_test.js
+++ b/src/node/test/interop_sanity_test.js
@@ -48,6 +48,9 @@ describe('Interop tests', function() {
port = 'localhost:' + server_obj.port;
done();
});
+ after(function() {
+ server.shutdown();
+ });
// This depends on not using a binary stream
it('should pass empty_unary', function(done) {
interop_client.runTest(port, name_override, 'empty_unary', true, done);
@@ -65,7 +68,7 @@ describe('Interop tests', function() {
it('should pass ping_pong', function(done) {
interop_client.runTest(port, name_override, 'ping_pong', true, done);
});
- it.skip('should pass empty_stream', function(done) {
+ it('should pass empty_stream', function(done) {
interop_client.runTest(port, name_override, 'empty_stream', true, done);
});
});
diff --git a/src/node/test/server_test.js b/src/node/test/server_test.js
index 457d13d2f5..5fad9a5564 100644
--- a/src/node/test/server_test.js
+++ b/src/node/test/server_test.js
@@ -33,7 +33,7 @@
var assert = require('assert');
var grpc = require('bindings')('grpc.node');
-var Server = require('../server');
+var Server = require('../src/server');
/**
* This is used for testing functions with multiple asynchronous calls that
@@ -65,17 +65,22 @@ function echoHandler(stream) {
}
describe('echo server', function() {
- it('should echo inputs as responses', function(done) {
- done = multiDone(done, 4);
- var server = new Server();
+ var server;
+ var channel;
+ before(function() {
+ server = new Server();
var port_num = server.bind('[::]:0');
server.register('echo', echoHandler);
server.start();
+ channel = new grpc.Channel('localhost:' + port_num);
+ });
+ it('should echo inputs as responses', function(done) {
+ done = multiDone(done, 4);
+
var req_text = 'echo test string';
var status_text = 'OK';
- var channel = new grpc.Channel('localhost:' + port_num);
var deadline = new Date();
deadline.setSeconds(deadline.getSeconds() + 3);
var call = new grpc.Call(channel,
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 34f1a156eb..85f4841d4b 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -33,7 +33,9 @@
var assert = require('assert');
-var surface_server = require('../surface_server.js');
+var surface_server = require('../src/surface_server.js');
+
+var surface_client = require('../src/surface_client.js');
var ProtoBuf = require('protobufjs');
@@ -73,3 +75,54 @@ describe('Surface server constructor', function() {
}, /math.Math/);
});
});
+describe('Surface client', function() {
+ var client;
+ var server;
+ before(function() {
+ var Server = grpc.buildServer([mathService]);
+ server = new Server({
+ 'math.Math': {
+ 'div': function(stream) {},
+ 'divMany': function(stream) {},
+ 'fib': function(stream) {},
+ 'sum': function(stream) {}
+ }
+ });
+ var port = server.bind('localhost:0');
+ var Client = surface_client.makeClientConstructor(mathService);
+ client = new Client('localhost:' + port);
+ });
+ after(function() {
+ server.shutdown();
+ });
+ it('Should correctly cancel a unary call', function(done) {
+ var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) {
+ assert.strictEqual(err.code, surface_client.status.CANCELLED);
+ done();
+ });
+ call.cancel();
+ });
+ it('Should correctly cancel a client stream call', function(done) {
+ var call = client.sum(function(err, resp) {
+ assert.strictEqual(err.code, surface_client.status.CANCELLED);
+ done();
+ });
+ call.cancel();
+ });
+ it('Should correctly cancel a server stream call', function(done) {
+ var call = client.fib({'limit': 5});
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, surface_client.status.CANCELLED);
+ done();
+ });
+ call.cancel();
+ });
+ it('Should correctly cancel a bidi stream call', function(done) {
+ var call = client.divMany();
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, surface_client.status.CANCELLED);
+ done();
+ });
+ call.cancel();
+ });
+});
diff --git a/src/ruby/README.md b/src/ruby/README.md
index 7f7558dc67..7ece7e2706 100755
--- a/src/ruby/README.md
+++ b/src/ruby/README.md
@@ -14,9 +14,10 @@ INSTALLING
----------
- Install the gRPC core library
-TODO: describe this, once the core distribution mechanism is defined.
-
+ TODO: describe this, once the core distribution mechanism is defined.
+```
$ gem install grpc
+```
Installing from source
@@ -24,37 +25,47 @@ Installing from source
- Build or Install the gRPC core
E.g, from the root of the grpc [git repo](https://github.com/google/grpc)
+```
$ cd ../..
$ make && sudo make install
+```
- Install Ruby 2.x. Consider doing this with [RVM](http://rvm.io), it's a nice way of controlling
the exact ruby version that's used.
+```
$ command curl -sSL https://rvm.io/mpapis.asc | gpg --import -
$ \curl -sSL https://get.rvm.io | bash -s stable --ruby
$
$ # follow the instructions to ensure that your're using the latest stable version of Ruby
$ # and that the rvm command is installed
+```
- Install [bundler](http://bundler.io/)
+```
$ gem install bundler
+```
- Finally, install grpc ruby locally.
+```
$ cd <install_dir>
$ bundle install
$ rake # compiles the extension, runs the unit tests, see rake -T for other options
-
+```
CONTENTS
--------
Directory structure is the layout for [ruby extensions](http://guides.rubygems.org/gems-with-extensions/)
- * ext: the extension code
- * lib: the entrypoint grpc ruby library to be used in a 'require' statement
- * spec: tests
- * bin: example gRPC clients and servers, e.g,
+- ext:
+ the gRPC ruby extension
+- lib:
+ the entrypoint grpc ruby library to be used in a 'require' statement
+- spec:
+ Rspec unittest
+- bin:
+ example gRPC clients and servers, e.g,
```ruby
-# client
stub = Math::Math::Stub.new('my.test.math.server.com:8080')
req = Math::DivArgs.new(dividend: 7, divisor: 3)
logger.info("div(7/3): req=#{req.inspect}")
diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb
index 0ea7f376be..86739b7b67 100755
--- a/src/ruby/bin/interop/interop_client.rb
+++ b/src/ruby/bin/interop/interop_client.rb
@@ -54,6 +54,8 @@ require 'test/cpp/interop/test_services'
require 'test/cpp/interop/messages'
require 'test/cpp/interop/empty'
+require 'signet/ssl_config'
+
# loads the certificates used to access the test server securely.
def load_test_certs
this_dir = File.expand_path(File.dirname(__FILE__))
@@ -62,21 +64,49 @@ def load_test_certs
files.map { |f| File.open(File.join(data_dir, f)).read }
end
+# loads the certificates used to access the test server securely.
+def load_prod_cert
+ fail 'could not find a production cert' if ENV['SSL_CERT_FILE'].nil?
+ p "loading prod certs from #{ENV['SSL_CERT_FILE']}"
+ File.open(ENV['SSL_CERT_FILE']).read
+end
+
# creates a Credentials from the test certificates.
def test_creds
certs = load_test_certs
GRPC::Core::Credentials.new(certs[0])
end
+RX_CERT = /-----BEGIN CERTIFICATE-----\n.*?-----END CERTIFICATE-----\n/m
+
+
+# creates a Credentials from the production certificates.
+def prod_creds
+ cert_text = load_prod_cert
+ GRPC::Core::Credentials.new(cert_text)
+end
+
# creates a test stub that accesses host:port securely.
-def create_stub(host, port)
+def create_stub(host, port, is_secure, host_override, use_test_ca)
address = "#{host}:#{port}"
- stub_opts = {
- :creds => test_creds,
- GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com'
- }
- logger.info("... connecting securely to #{address}")
- Grpc::Testing::TestService::Stub.new(address, **stub_opts)
+ if is_secure
+ creds = nil
+ if use_test_ca
+ creds = test_creds
+ else
+ creds = prod_creds
+ end
+
+ stub_opts = {
+ :creds => creds,
+ GRPC::Core::Channel::SSL_TARGET => host_override
+ }
+ logger.info("... connecting securely to #{address}")
+ Grpc::Testing::TestService::Stub.new(address, **stub_opts)
+ else
+ logger.info("... connecting insecurely to #{address}")
+ Grpc::Testing::TestService::Stub.new(address)
+ end
end
# produces a string of null chars (\0) of length l.
@@ -133,20 +163,12 @@ class NamedTests
@stub = stub
end
- # TESTING
- # PASSED
- # FAIL
- # ruby server: fails protobuf-ruby can't pass an empty message
def empty_unary
resp = @stub.empty_call(Empty.new)
assert resp.is_a?(Empty), 'empty_unary: invalid response'
p 'OK: empty_unary'
end
- # TESTING
- # PASSED
- # ruby server
- # FAILED
def large_unary
req_size, wanted_response_size = 271_828, 314_159
payload = Payload.new(type: :COMPRESSABLE, body: nulls(req_size))
@@ -163,10 +185,6 @@ class NamedTests
p 'OK: large_unary'
end
- # TESTING:
- # PASSED
- # ruby server
- # FAILED
def client_streaming
msg_sizes = [27_182, 8, 1828, 45_904]
wanted_aggregate_size = 74_922
@@ -180,10 +198,6 @@ class NamedTests
p 'OK: client_streaming'
end
- # TESTING:
- # PASSED
- # ruby server
- # FAILED
def server_streaming
msg_sizes = [31_415, 9, 2653, 58_979]
response_spec = msg_sizes.map { |s| ResponseParameters.new(size: s) }
@@ -200,10 +214,6 @@ class NamedTests
p 'OK: server_streaming'
end
- # TESTING:
- # PASSED
- # ruby server
- # FAILED
def ping_pong
msg_sizes = [[27_182, 31_415], [8, 9], [1828, 2653], [45_904, 58_979]]
ppp = PingPongPlayer.new(msg_sizes)
@@ -211,12 +221,23 @@ class NamedTests
resps.each { |r| ppp.queue.push(r) }
p 'OK: ping_pong'
end
+
+ def all
+ all_methods = NamedTests.instance_methods(false).map(&:to_s)
+ all_methods.each do |m|
+ next if m == 'all' || m.start_with?('assert')
+ p "TESTCASE: #{m}"
+ method(m).call
+ end
+ end
end
# validates the the command line options, returning them as a Hash.
def parse_options
options = {
+ 'secure' => false,
'server_host' => nil,
+ 'server_host_override' => nil,
'server_port' => nil,
'test_case' => nil
}
@@ -225,6 +246,10 @@ def parse_options
opts.on('--server_host SERVER_HOST', 'server hostname') do |v|
options['server_host'] = v
end
+ opts.on('--server_host_override HOST_OVERRIDE',
+ 'override host via a HTTP header') do |v|
+ options['server_host_override'] = v
+ end
opts.on('--server_port SERVER_PORT', 'server port') do |v|
options['server_port'] = v
end
@@ -235,19 +260,33 @@ def parse_options
" (#{test_case_list})") do |v|
options['test_case'] = v
end
+ opts.on('-s', '--use_tls', 'require a secure connection?') do |v|
+ options['secure'] = v
+ end
+ opts.on('-t', '--use_test_ca',
+ 'if secure, use the test certificate?') do |v|
+ options['use_test_ca'] = v
+ end
end.parse!
+ _check_options(options)
+end
+def _check_options(opts)
%w(server_host server_port test_case).each do |arg|
- if options[arg].nil?
+ if opts[arg].nil?
fail(OptionParser::MissingArgument, "please specify --#{arg}")
end
end
- options
+ if opts['server_host_override'].nil?
+ opts['server_host_override'] = opts['server_host']
+ end
+ opts
end
def main
opts = parse_options
- stub = create_stub(opts['server_host'], opts['server_port'])
+ stub = create_stub(opts['server_host'], opts['server_port'], opts['secure'],
+ opts['server_host_override'], opts['use_test_ca'])
NamedTests.new(stub).method(opts['test_case']).call
end
diff --git a/src/ruby/bin/interop/interop_server.rb b/src/ruby/bin/interop/interop_server.rb
index 83212823f6..cc4d260879 100755
--- a/src/ruby/bin/interop/interop_server.rb
+++ b/src/ruby/bin/interop/interop_server.rb
@@ -154,13 +154,17 @@ end
# validates the the command line options, returning them as a Hash.
def parse_options
options = {
- 'port' => nil
+ 'port' => nil,
+ 'secure' => false
}
OptionParser.new do |opts|
opts.banner = 'Usage: --port port'
opts.on('--port PORT', 'server port') do |v|
options['port'] = v
end
+ opts.on('-s', '--use_tls', 'require a secure connection?') do |v|
+ options['secure'] = v
+ end
end.parse!
if options['port'].nil?
@@ -172,10 +176,15 @@ end
def main
opts = parse_options
host = "0.0.0.0:#{opts['port']}"
- s = GRPC::RpcServer.new(creds: test_server_creds)
- s.add_http2_port(host, true)
- logger.info("... running securely on #{host}")
-
+ if opts['secure']
+ s = GRPC::RpcServer.new(creds: test_server_creds)
+ s.add_http2_port(host, true)
+ logger.info("... running securely on #{host}")
+ else
+ s = GRPC::RpcServer.new
+ s.add_http2_port(host)
+ logger.info("... running insecurely on #{host}")
+ end
s.handle(TestTarget)
s.run
end
diff --git a/src/ruby/ext/grpc/rb_credentials.c b/src/ruby/ext/grpc/rb_credentials.c
index 50426dece8..87a5d0a299 100644
--- a/src/ruby/ext/grpc/rb_credentials.c
+++ b/src/ruby/ext/grpc/rb_credentials.c
@@ -84,7 +84,6 @@ static void grpc_rb_credentials_mark(void *p) {
}
/* Allocates Credential instances.
-
Provides safe initial defaults for the instance fields. */
static VALUE grpc_rb_credentials_alloc(VALUE cls) {
grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials);
@@ -95,7 +94,6 @@ static VALUE grpc_rb_credentials_alloc(VALUE cls) {
}
/* Clones Credentials instances.
-
Gives Credentials a consistent implementation of Ruby's object copy/dup
protocol. */
static VALUE grpc_rb_credentials_init_copy(VALUE copy, VALUE orig) {
@@ -124,7 +122,6 @@ static VALUE grpc_rb_credentials_init_copy(VALUE copy, VALUE orig) {
/*
call-seq:
creds = Credentials.default()
-
Creates the default credential instances. */
static VALUE grpc_rb_default_credentials_create(VALUE cls) {
grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials);
@@ -143,7 +140,6 @@ static VALUE grpc_rb_default_credentials_create(VALUE cls) {
/*
call-seq:
creds = Credentials.compute_engine()
-
Creates the default credential instances. */
static VALUE grpc_rb_compute_engine_credentials_create(VALUE cls) {
grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials);
@@ -164,7 +160,6 @@ static VALUE grpc_rb_compute_engine_credentials_create(VALUE cls) {
creds1 = ...
creds2 = ...
creds3 = creds1.add(creds2)
-
Creates the default credential instances. */
static VALUE grpc_rb_composite_credentials_create(VALUE self, VALUE other) {
grpc_rb_credentials *self_wrapper = NULL;
@@ -202,11 +197,9 @@ static ID id_pem_cert_chain;
...
creds2 = Credentials.new(pem_root_certs, pem_private_key,
pem_cert_chain)
-
pem_root_certs: (required) PEM encoding of the server root certificate
pem_private_key: (optional) PEM encoding of the client's private key
pem_cert_chain: (optional) PEM encoding of the client's cert chain
-
Initializes Credential instances. */
static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
VALUE pem_root_certs = Qnil;
@@ -214,6 +207,8 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
VALUE pem_cert_chain = Qnil;
grpc_rb_credentials *wrapper = NULL;
grpc_credentials *creds = NULL;
+ grpc_ssl_pem_key_cert_pair key_cert_pair;
+ MEMZERO(&key_cert_pair, grpc_ssl_pem_key_cert_pair, 1);
/* TODO: Remove mandatory arg when we support default roots. */
/* "12" == 1 mandatory arg, 2 (credentials) is optional */
rb_scan_args(argc, argv, "12", &pem_root_certs, &pem_private_key,
@@ -228,10 +223,10 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
if (pem_private_key == Qnil && pem_cert_chain == Qnil) {
creds = grpc_ssl_credentials_create(RSTRING_PTR(pem_root_certs), NULL);
} else {
- grpc_ssl_pem_key_cert_pair key_cert_pair = {RSTRING_PTR(pem_private_key),
- RSTRING_PTR(pem_cert_chain)};
- creds = grpc_ssl_credentials_create(RSTRING_PTR(pem_root_certs),
- &key_cert_pair);
+ key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
+ key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
+ creds = grpc_ssl_credentials_create(
+ RSTRING_PTR(pem_root_certs), &key_cert_pair);
}
if (creds == NULL) {
rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index ef2a9f107b..436d006760 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -223,7 +223,7 @@ static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) {
VALUE port = Qnil;
VALUE is_secure = Qnil;
grpc_rb_server *s = NULL;
- int added_ok = 0;
+ int recvd_port = 0;
/* "11" == 1 mandatory args, 1 (is_secure) is optional */
rb_scan_args(argc, argv, "11", &port, &is_secure);
@@ -233,22 +233,22 @@ static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) {
rb_raise(rb_eRuntimeError, "closed!");
return Qnil;
} else if (is_secure == Qnil || TYPE(is_secure) != T_TRUE) {
- added_ok = grpc_server_add_http2_port(s->wrapped, StringValueCStr(port));
- if (added_ok == 0) {
+ recvd_port = grpc_server_add_http2_port(s->wrapped, StringValueCStr(port));
+ if (recvd_port == 0) {
rb_raise(rb_eRuntimeError,
"could not add port %s to server, not sure why",
StringValueCStr(port));
}
} else if (TYPE(is_secure) != T_FALSE) {
- added_ok =
+ recvd_port =
grpc_server_add_secure_http2_port(s->wrapped, StringValueCStr(port));
- if (added_ok == 0) {
+ if (recvd_port == 0) {
rb_raise(rb_eRuntimeError,
"could not add secure port %s to server, not sure why",
StringValueCStr(port));
}
}
- return Qnil;
+ return INT2NUM(recvd_port);
}
void Init_google_rpc_server() {
diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec
index 450362f5a8..ffd084dc91 100755
--- a/src/ruby/grpc.gemspec
+++ b/src/ruby/grpc.gemspec
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
s.add_dependency 'xray'
s.add_dependency 'logging', '~> 1.8'
s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1'
+ s.add_dependency 'signet', '~> 0.5.1'
s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests
s.add_development_dependency 'bundler', '~> 1.7'
diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb
index 1cdc168bfe..6c2b6e91c2 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -67,7 +67,7 @@ module Google
fail(ArgumentError, 'not a CompletionQueue')
end
call.add_metadata(kw) if kw.length > 0
- invoke_accepted, client_metadata_read = Object.new, Object.new
+ client_metadata_read = Object.new
finished_tag = Object.new
call.invoke(q, client_metadata_read, finished_tag)
[finished_tag, client_metadata_read]
diff --git a/src/ruby/spec/call_spec.rb b/src/ruby/spec/call_spec.rb
index 9a510df1f3..c793284488 100644
--- a/src/ruby/spec/call_spec.rb
+++ b/src/ruby/spec/call_spec.rb
@@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require 'port_picker'
include GRPC::Core::StatusCodes
@@ -71,16 +70,8 @@ describe GRPC::Core::Call do
before(:each) do
@tag = Object.new
@client_queue = GRPC::Core::CompletionQueue.new
- @server_queue = GRPC::Core::CompletionQueue.new
- port = find_unused_tcp_port
- host = "localhost:#{port}"
- @server = GRPC::Core::Server.new(@server_queue, nil)
- @server.add_http2_port(host)
- @ch = GRPC::Core::Channel.new(host, nil)
- end
-
- after(:each) do
- @server.close
+ fake_host = 'localhost:10101'
+ @ch = GRPC::Core::Channel.new(fake_host, nil)
end
describe '#start_read' do
@@ -122,19 +113,6 @@ describe GRPC::Core::Call do
end
end
- describe '#start_write' do
- it 'should cause the WRITE_ACCEPTED event' do
- call = make_test_call
- call.invoke(@client_queue, @tag, @tag)
- expect(call.start_write(GRPC::Core::ByteBuffer.new('test_start_write'),
- @tag)).to be_nil
- ev = @client_queue.next(deadline)
- expect(ev.call).to be_a(GRPC::Core::Call)
- expect(ev.type).to be(GRPC::Core::CompletionType::WRITE_ACCEPTED)
- expect(ev.tag).to be(@tag)
- end
- end
-
describe '#status' do
it 'can save the status and read it back' do
call = make_test_call
diff --git a/src/ruby/spec/channel_spec.rb b/src/ruby/spec/channel_spec.rb
index 820dbd39e9..189d1c67ab 100644
--- a/src/ruby/spec/channel_spec.rb
+++ b/src/ruby/spec/channel_spec.rb
@@ -28,7 +28,8 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require 'port_picker'
+
+FAKE_HOST='localhost:0'
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')
@@ -114,8 +115,7 @@ describe GRPC::Core::Channel do
describe '#create_call' do
it 'creates a call OK' do
- port = find_unused_tcp_port
- host = "localhost:#{port}"
+ host = FAKE_HOST
ch = GRPC::Core::Channel.new(host, nil)
deadline = Time.now + 5
@@ -127,8 +127,7 @@ describe GRPC::Core::Channel do
end
it 'raises an error if called on a closed channel' do
- port = find_unused_tcp_port
- host = "localhost:#{port}"
+ host = FAKE_HOST
ch = GRPC::Core::Channel.new(host, nil)
ch.close
@@ -142,16 +141,14 @@ describe GRPC::Core::Channel do
describe '#destroy' do
it 'destroys a channel ok' do
- port = find_unused_tcp_port
- host = "localhost:#{port}"
+ host = FAKE_HOST
ch = GRPC::Core::Channel.new(host, nil)
blk = proc { ch.destroy }
expect(&blk).to_not raise_error
end
it 'can be called more than once without error' do
- port = find_unused_tcp_port
- host = "localhost:#{port}"
+ host = FAKE_HOST
ch = GRPC::Core::Channel.new(host, nil)
blk = proc { ch.destroy }
blk.call
@@ -167,16 +164,14 @@ describe GRPC::Core::Channel do
describe '#close' do
it 'closes a channel ok' do
- port = find_unused_tcp_port
- host = "localhost:#{port}"
+ host = FAKE_HOST
ch = GRPC::Core::Channel.new(host, nil)
blk = proc { ch.close }
expect(&blk).to_not raise_error
end
it 'can be called more than once without error' do
- port = find_unused_tcp_port
- host = "localhost:#{port}"
+ host = FAKE_HOST
ch = GRPC::Core::Channel.new(host, nil)
blk = proc { ch.close }
blk.call
diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb
index b2afb0581e..96b8ef4300 100644
--- a/src/ruby/spec/client_server_spec.rb
+++ b/src/ruby/spec/client_server_spec.rb
@@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require 'port_picker'
require 'spec_helper'
include GRPC::Core::CompletionType
@@ -44,12 +43,13 @@ shared_context 'setup: tags' do
before(:example) do
@server_finished_tag = Object.new
@client_finished_tag = Object.new
+ @client_metadata_tag = Object.new
@server_tag = Object.new
@tag = Object.new
end
def deadline
- Time.now + 0.05
+ Time.now + 2
end
def expect_next_event_on(queue, type, tag)
@@ -63,27 +63,30 @@ shared_context 'setup: tags' do
ev
end
- def server_receives_and_responds_with(reply_text)
- reply = ByteBuffer.new(reply_text)
+ def server_allows_client_to_proceed
@server.request_call(@server_tag)
- ev = @server_queue.pluck(@server_tag, TimeConsts::INFINITE_FUTURE)
+ ev = @server_queue.pluck(@server_tag, deadline)
expect(ev).not_to be_nil
expect(ev.type).to be(SERVER_RPC_NEW)
- ev.call.server_accept(@server_queue, @server_finished_tag)
- ev.call.server_end_initial_metadata
- ev.call.start_read(@server_tag)
+ server_call = ev.call
+ server_call.server_accept(@server_queue, @server_finished_tag)
+ server_call.server_end_initial_metadata
+ server_call
+ end
+
+ def server_responds_with(server_call, reply_text)
+ reply = ByteBuffer.new(reply_text)
+ server_call.start_read(@server_tag)
ev = @server_queue.pluck(@server_tag, TimeConsts::INFINITE_FUTURE)
expect(ev.type).to be(READ)
- ev.call.start_write(reply, @server_tag)
+ server_call.start_write(reply, @server_tag)
ev = @server_queue.pluck(@server_tag, TimeConsts::INFINITE_FUTURE)
expect(ev).not_to be_nil
expect(ev.type).to be(WRITE_ACCEPTED)
- ev.call
end
def client_sends(call, sent = 'a message')
req = ByteBuffer.new(sent)
- call.invoke(@client_queue, @tag, @client_finished_tag)
call.start_write(req, @tag)
ev = @client_queue.pluck(@tag, TimeConsts::INFINITE_FUTURE)
expect(ev).not_to be_nil
@@ -102,16 +105,20 @@ shared_examples 'basic GRPC message delivery is OK' do
it 'servers receive requests from clients and start responding' do
reply = ByteBuffer.new('the server payload')
call = new_client_call
- msg = client_sends(call)
+ call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
# check the server rpc new was received
- @server.request_call(@server_tag)
- ev = expect_next_event_on(@server_queue, SERVER_RPC_NEW, @server_tag)
+ # @server.request_call(@server_tag)
+ # ev = expect_next_event_on(@server_queue, SERVER_RPC_NEW, @server_tag)
# accept the call
- server_call = ev.call
- server_call.server_accept(@server_queue, @server_finished_tag)
- server_call.server_end_initial_metadata
+ # server_call = ev.call
+ # server_call.server_accept(@server_queue, @server_finished_tag)
+ # server_call.server_end_initial_metadata
+ server_call = server_allows_client_to_proceed
+
+ # client sends a message
+ msg = client_sends(call)
# confirm the server can read the inbound message
server_call.start_read(@server_tag)
@@ -125,18 +132,19 @@ shared_examples 'basic GRPC message delivery is OK' do
it 'responses written by servers are received by the client' do
call = new_client_call
+ call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
+ server_call = server_allows_client_to_proceed
client_sends(call)
- server_receives_and_responds_with('server_response')
+ server_responds_with(server_call, 'server_response')
call.start_read(@tag)
- expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag)
ev = expect_next_event_on(@client_queue, READ, @tag)
expect(ev.result.to_s).to eq('server_response')
end
it 'servers can ignore a client write and send a status' do
call = new_client_call
- client_sends(call)
+ call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
# check the server rpc new was received
@server.request_call(@server_tag)
@@ -150,9 +158,13 @@ shared_examples 'basic GRPC message delivery is OK' do
server_call.start_write_status(StatusCodes::NOT_FOUND, 'not found',
@server_tag)
+ # Client sends some data
+ client_sends(call)
+
# client gets an empty response for the read, preceeded by some metadata.
call.start_read(@tag)
- expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag)
+ expect_next_event_on(@client_queue, CLIENT_METADATA_READ,
+ @client_metadata_tag)
ev = expect_next_event_on(@client_queue, READ, @tag)
expect(ev.tag).to be(@tag)
expect(ev.result.to_s).to eq('')
@@ -166,13 +178,14 @@ shared_examples 'basic GRPC message delivery is OK' do
it 'completes calls by sending status to client and server' do
call = new_client_call
+ call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
+ server_call = server_allows_client_to_proceed
client_sends(call)
- server_call = server_receives_and_responds_with('server_response')
+ server_responds_with(server_call, 'server_response')
server_call.start_write_status(10_101, 'status code is 10101', @server_tag)
# first the client says writes are done
call.start_read(@tag)
- expect_next_event_on(@client_queue, CLIENT_METADATA_READ, @tag)
expect_next_event_on(@client_queue, READ, @tag)
call.writes_done(@tag)
@@ -215,22 +228,13 @@ shared_examples 'GRPC metadata delivery works OK' do
end
end
- it 'sends an empty hash when no metadata is added' do
- call = new_client_call
- client_sends(call)
-
- # Server gets a response
- @server.request_call(@server_tag)
- expect_next_event_on(@server_queue, SERVER_RPC_NEW, @server_tag)
- end
-
it 'sends all the metadata pairs when keys and values are valid' do
@valid_metadata.each do |md|
call = new_client_call
call.add_metadata(md)
# Client begins a call OK
- call.invoke(@client_queue, @tag, @client_finished_tag)
+ call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
# ... server has all metadata available even though the client did not
# send a write
@@ -262,7 +266,7 @@ shared_examples 'GRPC metadata delivery works OK' do
it 'raises an exception if a metadata key is invalid' do
@bad_keys.each do |md|
call = new_client_call
- client_sends(call)
+ call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
# server gets the invocation
@server.request_call(@server_tag)
@@ -273,7 +277,7 @@ shared_examples 'GRPC metadata delivery works OK' do
it 'sends a hash that contains the status when no metadata is added' do
call = new_client_call
- client_sends(call)
+ call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
# server gets the invocation
@server.request_call(@server_tag)
@@ -284,21 +288,17 @@ shared_examples 'GRPC metadata delivery works OK' do
server_call.server_accept(@server_queue, @server_finished_tag)
server_call.server_end_initial_metadata
- # ... these server sends some data, allowing the metadata read
- server_call.start_write(ByteBuffer.new('reply with metadata'),
- @server_tag)
- expect_next_event_on(@server_queue, WRITE_ACCEPTED, @server_tag)
-
# there is the HTTP status metadata, though there should not be any
# TODO: 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,
+ @client_metadata_tag)
expect(ev.result).to eq(':status' => '200')
end
it 'sends all the pairs and status:200 when keys and values are valid' do
@valid_metadata.each do |md|
call = new_client_call
- client_sends(call)
+ call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
# server gets the invocation
@server.request_call(@server_tag)
@@ -311,7 +311,8 @@ shared_examples 'GRPC metadata delivery works OK' do
server_call.server_end_initial_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,
+ @client_metadata_tag)
replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
replace_symbols[':status'] = '200'
expect(ev.result).to eq(replace_symbols)
@@ -322,17 +323,17 @@ end
describe 'the http client/server' do
before(:example) do
- port = find_unused_tcp_port
- host = "localhost:#{port}"
+ server_host = '0.0.0.0:0'
@client_queue = GRPC::Core::CompletionQueue.new
@server_queue = GRPC::Core::CompletionQueue.new
@server = GRPC::Core::Server.new(@server_queue, nil)
- @server.add_http2_port(host)
+ server_port = @server.add_http2_port(server_host)
@server.start
- @ch = Channel.new(host, nil)
+ @ch = Channel.new("0.0.0.0:#{server_port}", nil)
end
after(:example) do
+ @ch.close
@server.close
end
@@ -346,16 +347,15 @@ end
describe 'the secure http client/server' do
before(:example) do
certs = load_test_certs
- port = find_unused_tcp_port
- host = "localhost:#{port}"
+ server_host = 'localhost:0'
@client_queue = GRPC::Core::CompletionQueue.new
@server_queue = GRPC::Core::CompletionQueue.new
server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
@server = GRPC::Core::Server.new(@server_queue, nil, server_creds)
- @server.add_http2_port(host, true)
+ server_port = @server.add_http2_port(server_host, true)
@server.start
args = { Channel::SSL_TARGET => 'foo.test.google.com' }
- @ch = Channel.new(host, args,
+ @ch = Channel.new("0.0.0.0:#{server_port}", args,
GRPC::Core::Credentials.new(certs[0], nil, nil))
end
diff --git a/src/ruby/spec/generic/active_call_spec.rb b/src/ruby/spec/generic/active_call_spec.rb
index 443ba3d192..e81b2168b0 100644
--- a/src/ruby/spec/generic/active_call_spec.rb
+++ b/src/ruby/spec/generic/active_call_spec.rb
@@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require_relative '../port_picker'
include GRPC::Core::StatusCodes
@@ -45,12 +44,11 @@ describe GRPC::ActiveCall do
@client_queue = GRPC::Core::CompletionQueue.new
@server_queue = GRPC::Core::CompletionQueue.new
- port = find_unused_tcp_port
- host = "localhost:#{port}"
+ host = '0.0.0.0:0'
@server = GRPC::Core::Server.new(@server_queue, nil)
- @server.add_http2_port(host)
+ server_port = @server.add_http2_port(host)
@server.start
- @ch = GRPC::Core::Channel.new(host, nil)
+ @ch = GRPC::Core::Channel.new("localhost:#{server_port}", nil)
end
after(:each) do
@@ -206,7 +204,7 @@ describe GRPC::ActiveCall do
it 'get a nil msg before a status when an OK status is sent' do
call = make_test_call
done_tag, meta_tag = ActiveCall.client_invoke(call, @client_queue,
- deadline)
+ deadline)
client_call = ActiveCall.new(call, @client_queue, @pass_through,
@pass_through, deadline,
finished_tag: done_tag,
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index 8ebe48bc4c..f1500fbd44 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -29,9 +29,9 @@
require 'grpc'
require 'xray/thread_dump_signal_handler'
-require_relative '../port_picker'
NOOP = proc { |x| x }
+FAKE_HOST = 'localhost:0'
def wakey_thread(&blk)
awake_mutex, awake_cond = Mutex.new, ConditionVariable.new
@@ -67,7 +67,7 @@ describe 'ClientStub' do
describe '#new' do
it 'can be created from a host and args' do
- host = new_test_host
+ host = FAKE_HOST
opts = { a_channel_arg: 'an_arg' }
blk = proc do
GRPC::ClientStub.new(host, @cq, **opts)
@@ -76,7 +76,7 @@ describe 'ClientStub' do
end
it 'can be created with a default deadline' do
- host = new_test_host
+ host = FAKE_HOST
opts = { a_channel_arg: 'an_arg', deadline: 5 }
blk = proc do
GRPC::ClientStub.new(host, @cq, **opts)
@@ -85,7 +85,7 @@ describe 'ClientStub' do
end
it 'can be created with an channel override' do
- host = new_test_host
+ host = FAKE_HOST
opts = { a_channel_arg: 'an_arg', channel_override: @ch }
blk = proc do
GRPC::ClientStub.new(host, @cq, **opts)
@@ -94,7 +94,7 @@ describe 'ClientStub' do
end
it 'cannot be created with a bad channel override' do
- host = new_test_host
+ host = FAKE_HOST
blk = proc do
opts = { a_channel_arg: 'an_arg', channel_override: Object.new }
GRPC::ClientStub.new(host, @cq, **opts)
@@ -103,7 +103,7 @@ describe 'ClientStub' do
end
it 'cannot be created with bad credentials' do
- host = new_test_host
+ host = FAKE_HOST
blk = proc do
opts = { a_channel_arg: 'an_arg', creds: Object.new }
GRPC::ClientStub.new(host, @cq, **opts)
@@ -113,7 +113,7 @@ describe 'ClientStub' do
it 'can be created with test test credentials' do
certs = load_test_certs
- host = new_test_host
+ host = FAKE_HOST
blk = proc do
opts = {
GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com',
@@ -133,16 +133,17 @@ describe 'ClientStub' do
shared_examples 'request response' do
it 'should send a request to/receive a reply from a server' do
- host = new_test_host
- th = run_request_response(host, @sent_msg, @resp, @pass)
- stub = GRPC::ClientStub.new(host, @cq)
+ server_port = create_test_server
+ th = run_request_response(@sent_msg, @resp, @pass)
+ stub = GRPC::ClientStub.new("localhost:#{server_port}", @cq)
expect(get_response(stub)).to eq(@resp)
th.join
end
it 'should send metadata to the server ok' do
- host = new_test_host
- th = run_request_response(host, @sent_msg, @resp, @pass,
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_request_response(@sent_msg, @resp, @pass,
k1: 'v1', k2: 'v2')
stub = GRPC::ClientStub.new(host, @cq)
expect(get_response(stub)).to eq(@resp)
@@ -150,8 +151,9 @@ describe 'ClientStub' do
end
it 'should update the sent metadata with a provided metadata updater' do
- host = new_test_host
- th = run_request_response(host, @sent_msg, @resp, @pass,
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_request_response(@sent_msg, @resp, @pass,
k1: 'updated-v1', k2: 'v2')
update_md = proc do |md|
md[:k1] = 'updated-v1'
@@ -163,8 +165,9 @@ describe 'ClientStub' do
end
it 'should send a request when configured using an override channel' do
- alt_host = new_test_host
- th = run_request_response(alt_host, @sent_msg, @resp, @pass)
+ server_port = create_test_server
+ alt_host = "localhost:#{server_port}"
+ th = run_request_response(@sent_msg, @resp, @pass)
ch = GRPC::Core::Channel.new(alt_host, nil)
stub = GRPC::ClientStub.new('ignored-host', @cq, channel_override: ch)
expect(get_response(stub)).to eq(@resp)
@@ -172,8 +175,9 @@ describe 'ClientStub' do
end
it 'should raise an error if the status is not OK' do
- host = new_test_host
- th = run_request_response(host, @sent_msg, @resp, @fail)
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_request_response(@sent_msg, @resp, @fail)
stub = GRPC::ClientStub.new(host, @cq)
blk = proc { get_response(stub) }
expect(&blk).to raise_error(GRPC::BadStatus)
@@ -210,16 +214,18 @@ describe 'ClientStub' do
end
it 'should send requests to/receive a reply from a server' do
- host = new_test_host
- th = run_client_streamer(host, @sent_msgs, @resp, @pass)
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_client_streamer(@sent_msgs, @resp, @pass)
stub = GRPC::ClientStub.new(host, @cq)
expect(get_response(stub)).to eq(@resp)
th.join
end
it 'should send metadata to the server ok' do
- host = new_test_host
- th = run_client_streamer(host, @sent_msgs, @resp, @pass,
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_client_streamer(@sent_msgs, @resp, @pass,
k1: 'v1', k2: 'v2')
stub = GRPC::ClientStub.new(host, @cq)
expect(get_response(stub)).to eq(@resp)
@@ -227,8 +233,9 @@ describe 'ClientStub' do
end
it 'should update the sent metadata with a provided metadata updater' do
- host = new_test_host
- th = run_client_streamer(host, @sent_msgs, @resp, @pass,
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_client_streamer(@sent_msgs, @resp, @pass,
k1: 'updated-v1', k2: 'v2')
update_md = proc do |md|
md[:k1] = 'updated-v1'
@@ -240,8 +247,9 @@ describe 'ClientStub' do
end
it 'should raise an error if the status is not ok' do
- host = new_test_host
- th = run_client_streamer(host, @sent_msgs, @resp, @fail)
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_client_streamer(@sent_msgs, @resp, @fail)
stub = GRPC::ClientStub.new(host, @cq)
blk = proc { get_response(stub) }
expect(&blk).to raise_error(GRPC::BadStatus)
@@ -278,16 +286,18 @@ describe 'ClientStub' do
end
it 'should send a request to/receive replies from a server' do
- host = new_test_host
- th = run_server_streamer(host, @sent_msg, @replys, @pass)
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_server_streamer(@sent_msg, @replys, @pass)
stub = GRPC::ClientStub.new(host, @cq)
expect(get_responses(stub).collect { |r| r }).to eq(@replys)
th.join
end
it 'should raise an error if the status is not ok' do
- host = new_test_host
- th = run_server_streamer(host, @sent_msg, @replys, @fail)
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_server_streamer(@sent_msg, @replys, @fail)
stub = GRPC::ClientStub.new(host, @cq)
e = get_responses(stub)
expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus)
@@ -295,8 +305,9 @@ describe 'ClientStub' do
end
it 'should send metadata to the server ok' do
- host = new_test_host
- th = run_server_streamer(host, @sent_msg, @replys, @fail,
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_server_streamer(@sent_msg, @replys, @fail,
k1: 'v1', k2: 'v2')
stub = GRPC::ClientStub.new(host, @cq)
e = get_responses(stub)
@@ -305,8 +316,9 @@ describe 'ClientStub' do
end
it 'should update the sent metadata with a provided metadata updater' do
- host = new_test_host
- th = run_server_streamer(host, @sent_msg, @replys, @pass,
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_server_streamer(@sent_msg, @replys, @pass,
k1: 'updated-v1', k2: 'v2')
update_md = proc do |md|
md[:k1] = 'updated-v1'
@@ -352,8 +364,9 @@ describe 'ClientStub' do
end
it 'supports sending all the requests first', bidi: true do
- host = new_test_host
- th = run_bidi_streamer_handle_inputs_first(host, @sent_msgs, @replys,
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_bidi_streamer_handle_inputs_first(@sent_msgs, @replys,
@pass)
stub = GRPC::ClientStub.new(host, @cq)
e = get_responses(stub)
@@ -362,8 +375,9 @@ describe 'ClientStub' do
end
it 'supports client-initiated ping pong', bidi: true do
- host = new_test_host
- th = run_bidi_streamer_echo_ping_pong(host, @sent_msgs, @pass, true)
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_bidi_streamer_echo_ping_pong(@sent_msgs, @pass, true)
stub = GRPC::ClientStub.new(host, @cq)
e = get_responses(stub)
expect(e.collect { |r| r }).to eq(@sent_msgs)
@@ -377,8 +391,9 @@ describe 'ClientStub' do
# they receive a message from the client. Without receiving all the
# metadata, the server does not accept the call, so this test hangs.
xit 'supports a server-initiated ping pong', bidi: true do
- host = new_test_host
- th = run_bidi_streamer_echo_ping_pong(host, @sent_msgs, @pass, false)
+ server_port = create_test_server
+ host = "localhost:#{server_port}"
+ th = run_bidi_streamer_echo_ping_pong(@sent_msgs, @pass, false)
stub = GRPC::ClientStub.new(host, @cq)
e = get_responses(stub)
expect(e.collect { |r| r }).to eq(@sent_msgs)
@@ -410,10 +425,10 @@ describe 'ClientStub' do
end
end
- def run_server_streamer(hostname, expected_input, replys, status, **kw)
+ def run_server_streamer(expected_input, replys, status, **kw)
wanted_metadata = kw.clone
wakey_thread do |mtx, cnd|
- c = expect_server_to_be_invoked(hostname, mtx, cnd)
+ c = expect_server_to_be_invoked(mtx, cnd)
wanted_metadata.each do |k, v|
expect(c.metadata[k.to_s]).to eq(v)
end
@@ -423,20 +438,19 @@ describe 'ClientStub' do
end
end
- def run_bidi_streamer_handle_inputs_first(hostname, expected_inputs, replys,
+ def run_bidi_streamer_handle_inputs_first(expected_inputs, replys,
status)
wakey_thread do |mtx, cnd|
- c = expect_server_to_be_invoked(hostname, mtx, cnd)
+ c = expect_server_to_be_invoked(mtx, cnd)
expected_inputs.each { |i| expect(c.remote_read).to eq(i) }
replys.each { |r| c.remote_send(r) }
c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
end
end
- def run_bidi_streamer_echo_ping_pong(hostname, expected_inputs, status,
- client_starts)
+ def run_bidi_streamer_echo_ping_pong(expected_inputs, status, client_starts)
wakey_thread do |mtx, cnd|
- c = expect_server_to_be_invoked(hostname, mtx, cnd)
+ c = expect_server_to_be_invoked(mtx, cnd)
expected_inputs.each do |i|
if client_starts
expect(c.remote_read).to eq(i)
@@ -450,10 +464,10 @@ describe 'ClientStub' do
end
end
- def run_client_streamer(hostname, expected_inputs, resp, status, **kw)
+ def run_client_streamer(expected_inputs, resp, status, **kw)
wanted_metadata = kw.clone
wakey_thread do |mtx, cnd|
- c = expect_server_to_be_invoked(hostname, mtx, cnd)
+ c = expect_server_to_be_invoked(mtx, cnd)
expected_inputs.each { |i| expect(c.remote_read).to eq(i) }
wanted_metadata.each do |k, v|
expect(c.metadata[k.to_s]).to eq(v)
@@ -463,10 +477,10 @@ describe 'ClientStub' do
end
end
- def run_request_response(hostname, expected_input, resp, status, **kw)
+ def run_request_response(expected_input, resp, status, **kw)
wanted_metadata = kw.clone
wakey_thread do |mtx, cnd|
- c = expect_server_to_be_invoked(hostname, mtx, cnd)
+ c = expect_server_to_be_invoked(mtx, cnd)
expect(c.remote_read).to eq(expected_input)
wanted_metadata.each do |k, v|
expect(c.metadata[k.to_s]).to eq(v)
@@ -476,32 +490,30 @@ describe 'ClientStub' do
end
end
- def start_test_server(hostname, awake_mutex, awake_cond)
- server_queue = GRPC::Core::CompletionQueue.new
- @server = GRPC::Core::Server.new(server_queue, nil)
- @server.add_http2_port(hostname)
+ def create_test_server
+ @server_queue = GRPC::Core::CompletionQueue.new
+ @server = GRPC::Core::Server.new(@server_queue, nil)
+ @server.add_http2_port('0.0.0.0:0')
+ end
+
+ def start_test_server(awake_mutex, awake_cond)
@server.start
@server_tag = Object.new
@server.request_call(@server_tag)
awake_mutex.synchronize { awake_cond.signal }
- server_queue
end
- def expect_server_to_be_invoked(hostname, awake_mutex, awake_cond)
- server_queue = start_test_server(hostname, awake_mutex, awake_cond)
- ev = server_queue.pluck(@server_tag, INFINITE_FUTURE)
+ def expect_server_to_be_invoked(awake_mutex, awake_cond)
+ start_test_server(awake_mutex, awake_cond)
+ ev = @server_queue.pluck(@server_tag, INFINITE_FUTURE)
fail OutOfTime if ev.nil?
server_call = ev.call
server_call.metadata = ev.result.metadata
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
- 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)
end
-
- def new_test_host
- port = find_unused_tcp_port
- "localhost:#{port}"
- end
end
diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb
index cd4888a3b4..e083bc1e9d 100644
--- a/src/ruby/spec/generic/rpc_server_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_spec.rb
@@ -29,7 +29,6 @@
require 'grpc'
require 'xray/thread_dump_signal_handler'
-require_relative '../port_picker'
def load_test_certs
test_root = File.join(File.dirname(File.dirname(__FILE__)), 'testdata')
@@ -104,10 +103,10 @@ describe GRPC::RpcServer do
@noop = proc { |x| x }
@server_queue = GRPC::Core::CompletionQueue.new
- port = find_unused_tcp_port
- @host = "localhost:#{port}"
+ server_host = '0.0.0.0:0'
@server = GRPC::Core::Server.new(@server_queue, nil)
- @server.add_http2_port(@host)
+ server_port = @server.add_http2_port(server_host)
+ @host = "localhost:#{server_port}"
@ch = GRPC::Core::Channel.new(@host, nil)
end
diff --git a/src/ruby/spec/port_picker.rb b/src/ruby/spec/port_picker.rb
deleted file mode 100644
index 98ffbacc1b..0000000000
--- a/src/ruby/spec/port_picker.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# 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.
-
-require 'socket'
-
-# @param [Fixnum] the minimum port number to accept
-# @param [Fixnum] the maximum port number to accept
-# @return [Fixnum ]a free tcp port
-def find_unused_tcp_port(min = 32_768, max = 60_000)
- # Allow the system to assign a port, by specifying 0.
- # Loop until a port is assigned in the required range
- loop do
- socket = Socket.new(:INET, :STREAM, 0)
- socket.bind(Addrinfo.tcp('127.0.0.1', 0))
- p = socket.local_address.ip_port
- socket.close
- return p if p > min && p < max
- end
-end
diff --git a/src/ruby/spec/server_spec.rb b/src/ruby/spec/server_spec.rb
index 6e5bb523de..1550ba6566 100644
--- a/src/ruby/spec/server_spec.rb
+++ b/src/ruby/spec/server_spec.rb
@@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc'
-require 'port_picker'
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')
@@ -205,10 +204,8 @@ describe Server do
end
def start_a_server
- port = find_unused_tcp_port
- host = "localhost:#{port}"
s = Server.new(@cq, nil)
- s.add_http2_port(host)
+ s.add_http2_port('0.0.0.0:0')
s.start
s
end
diff --git a/test/core/channel/metadata_buffer_test.c b/test/core/channel/metadata_buffer_test.c
index 50fbcaea69..9d7e1591f8 100644
--- a/test/core/channel/metadata_buffer_test.c
+++ b/test/core/channel/metadata_buffer_test.c
@@ -32,6 +32,7 @@
*/
#include "src/core/channel/metadata_buffer.h"
+#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "test/core/util/test_config.h"
@@ -42,12 +43,12 @@
/* construct a buffer with some prefix followed by an integer converted to
a string */
static gpr_slice construct_buffer(size_t prefix_length, size_t index) {
- gpr_slice buffer = gpr_slice_malloc(prefix_length + 32);
+ gpr_slice buffer = gpr_slice_malloc(prefix_length + GPR_LTOA_MIN_BUFSIZE);
memset(GPR_SLICE_START_PTR(buffer), 'a', prefix_length);
GPR_SLICE_SET_LENGTH(
- buffer, prefix_length +
- sprintf((char *)GPR_SLICE_START_PTR(buffer) + prefix_length,
- "%d", (int)index));
+ buffer,
+ prefix_length +
+ gpr_ltoa(index, (char *)GPR_SLICE_START_PTR(buffer) + prefix_length));
return buffer;
}
diff --git a/test/core/echo/server.c b/test/core/echo/server.c
index 57b083779c..6b67334248 100644
--- a/test/core/echo/server.c
+++ b/test/core/echo/server.c
@@ -32,6 +32,8 @@
*/
#include <grpc/grpc.h>
+#include <grpc/grpc_http.h>
+#include <grpc/grpc_security.h>
#include <signal.h>
#include <stdio.h>
@@ -42,10 +44,12 @@
#include "src/core/support/string.h"
#include "test/core/util/test_config.h"
#include <grpc/support/alloc.h>
+#include <grpc/support/cmdline.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "test/core/util/port.h"
+#include "test/core/end2end/data/ssl_test_data.h"
static grpc_completion_queue *cq;
static grpc_server *server;
@@ -83,29 +87,74 @@ static void sigint_handler(int x) { got_sigint = 1; }
int main(int argc, char **argv) {
grpc_event *ev;
- char *addr;
call_state *s;
+ char *addr_buf = NULL;
+ gpr_cmdline *cl;
int shutdown_started = 0;
int shutdown_finished = 0;
- grpc_test_init(argc, argv);
+ int secure = 0;
+ char *addr = NULL;
+
+ char *fake_argv[1];
+
+#define MAX_ARGS 4
+ grpc_arg arge[MAX_ARGS];
+ grpc_arg *e;
+ grpc_channel_args args = {0, NULL};
+
+ grpc_http_server_page home_page = {"/", "text/html",
+ "<head>\n"
+ "<title>Echo Server</title>\n"
+ "</head>\n"
+ "<body>\n"
+ "Welcome to the world of the future!\n"
+ "</body>\n"};
+
+ GPR_ASSERT(argc >= 1);
+ fake_argv[0] = argv[0];
+ grpc_test_init(1, fake_argv);
grpc_init();
srand(clock());
-
- if (argc == 2) {
- addr = gpr_strdup(argv[1]);
- } else {
- gpr_join_host_port(&addr, "::", grpc_pick_unused_port_or_die());
+ memset(arge, 0, sizeof(arge));
+ args.args = arge;
+
+ cl = gpr_cmdline_create("echo server");
+ gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr);
+ gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure);
+ gpr_cmdline_parse(cl, argc, argv);
+ gpr_cmdline_destroy(cl);
+
+ e = &arge[args.num_args++];
+ e->type = GRPC_ARG_POINTER;
+ e->key = GRPC_ARG_SERVE_OVER_HTTP;
+ e->value.pointer.p = &home_page;
+
+ if (addr == NULL) {
+ gpr_join_host_port(&addr_buf, "::", grpc_pick_unused_port_or_die());
+ addr = addr_buf;
}
gpr_log(GPR_INFO, "creating server on: %s", addr);
cq = grpc_completion_queue_create();
- server = grpc_server_create(cq, NULL);
- GPR_ASSERT(grpc_server_add_http2_port(server, addr));
- gpr_free(addr);
+ if (secure) {
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
+ test_server1_cert};
+ grpc_server_credentials *ssl_creds =
+ grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1);
+ server = grpc_secure_server_create(ssl_creds, cq, &args);
+ GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr));
+ grpc_server_credentials_release(ssl_creds);
+ } else {
+ server = grpc_server_create(cq, &args);
+ GPR_ASSERT(grpc_server_add_http2_port(server, addr));
+ }
grpc_server_start(server);
+ gpr_free(addr_buf);
+ addr = addr_buf = NULL;
+
request_call();
signal(SIGINT, sigint_handler);
diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c
index 49b131c236..287f83eebc 100644
--- a/test/core/end2end/cq_verifier.c
+++ b/test/core/end2end/cq_verifier.c
@@ -231,100 +231,91 @@ static void verify_matches(expectation *e, grpc_event *ev) {
}
}
-static char *metadata_expectation_string(metadata *md) {
- size_t len;
+static void metadata_expectation(gpr_strvec *buf, metadata *md) {
size_t i;
- char *out;
- char *p;
-
- if (!md) return gpr_strdup("nil");
-
- for (len = 0, i = 0; i < md->count; i++) {
- len += strlen(md->keys[i]);
- len += strlen(md->values[i]);
- }
- len += 3 + md->count;
-
- p = out = gpr_malloc(len);
- *p++ = '{';
- for (i = 0; i < md->count; i++) {
- if (i) *p++ = ',';
- p += sprintf(p, "%s:%s", md->keys[i], md->values[i]);
+ char *tmp;
+
+ if (!md) {
+ gpr_strvec_add(buf, gpr_strdup("nil"));
+ } else {
+ for (i = 0; i < md->count; i++) {
+ gpr_asprintf(&tmp, "%c%s:%s", i ? ',' : '{', md->keys[i], md->values[i]);
+ gpr_strvec_add(buf, tmp);
+ }
+ gpr_strvec_add(buf, gpr_strdup("}"));
}
- *p++ = '}';
- *p++ = 0;
- return out;
}
-static size_t expectation_to_string(char *out, expectation *e) {
+static void expectation_to_strvec(gpr_strvec *buf, expectation *e) {
gpr_timespec timeout;
- char *str = NULL;
- size_t len;
+ char *tmp;
switch (e->type) {
case GRPC_FINISH_ACCEPTED:
- return sprintf(out, "GRPC_FINISH_ACCEPTED result=%d",
+ gpr_asprintf(&tmp, "GRPC_FINISH_ACCEPTED result=%d",
e->data.finish_accepted);
+ gpr_strvec_add(buf, tmp);
+ break;
case GRPC_WRITE_ACCEPTED:
- return sprintf(out, "GRPC_WRITE_ACCEPTED result=%d",
+ gpr_asprintf(&tmp, "GRPC_WRITE_ACCEPTED result=%d",
e->data.write_accepted);
+ gpr_strvec_add(buf, tmp);
+ break;
case GRPC_INVOKE_ACCEPTED:
- return sprintf(out, "GRPC_INVOKE_ACCEPTED");
+ gpr_strvec_add(buf, gpr_strdup("GRPC_INVOKE_ACCEPTED"));
+ break;
case GRPC_SERVER_RPC_NEW:
timeout = gpr_time_sub(e->data.server_rpc_new.deadline, gpr_now());
- return sprintf(out, "GRPC_SERVER_RPC_NEW method=%s host=%s timeout=%fsec",
+ gpr_asprintf(&tmp, "GRPC_SERVER_RPC_NEW method=%s host=%s timeout=%fsec",
e->data.server_rpc_new.method, e->data.server_rpc_new.host,
timeout.tv_sec + 1e-9 * timeout.tv_nsec);
+ gpr_strvec_add(buf, tmp);
+ break;
case GRPC_CLIENT_METADATA_READ:
- str = metadata_expectation_string(e->data.client_metadata_read);
- len = sprintf(out, "GRPC_CLIENT_METADATA_READ %s", str);
- gpr_free(str);
- return len;
+ gpr_strvec_add(buf, gpr_strdup("GRPC_CLIENT_METADATA_READ "));
+ metadata_expectation(buf, e->data.client_metadata_read);
+ break;
case GRPC_FINISHED:
- str = metadata_expectation_string(e->data.finished.metadata);
- len = sprintf(out, "GRPC_FINISHED status=%d details=%s %s",
- e->data.finished.status, e->data.finished.details, str);
- gpr_free(str);
- return len;
+ gpr_asprintf(&tmp, "GRPC_FINISHED status=%d details=%s ",
+ e->data.finished.status, e->data.finished.details);
+ gpr_strvec_add(buf, tmp);
+ metadata_expectation(buf, e->data.finished.metadata);
+ break;
case GRPC_READ:
- if (e->data.read) {
- str =
- gpr_hexdump((char *)GPR_SLICE_START_PTR(*e->data.read),
- GPR_SLICE_LENGTH(*e->data.read), GPR_HEXDUMP_PLAINTEXT);
- }
- len = sprintf(out, "GRPC_READ data=%s", str);
- gpr_free(str);
- return len;
+ gpr_strvec_add(buf, gpr_strdup("GRPC_READ data="));
+ gpr_strvec_add(buf, gpr_hexdump((char *)GPR_SLICE_START_PTR(*e->data.read),
+ GPR_SLICE_LENGTH(*e->data.read), GPR_HEXDUMP_PLAINTEXT));
+ break;
case GRPC_SERVER_SHUTDOWN:
- return sprintf(out, "GRPC_SERVER_SHUTDOWN");
+ gpr_strvec_add(buf, gpr_strdup("GRPC_SERVER_SHUTDOWN"));
+ break;
case GRPC_COMPLETION_DO_NOT_USE:
case GRPC_QUEUE_SHUTDOWN:
gpr_log(GPR_ERROR, "not implemented");
abort();
break;
}
- return 0;
}
-static char *expectations_to_string(cq_verifier *v) {
- /* allocate a large buffer: we're about to crash anyway */
- char *buffer = gpr_malloc(32 * 1024 * 1024);
- char *p = buffer;
+static void expectations_to_strvec(gpr_strvec *buf, cq_verifier *v) {
expectation *e;
for (e = v->expect.next; e != &v->expect; e = e->next) {
- p += expectation_to_string(p, e);
- *p++ = '\n';
+ expectation_to_strvec(buf, e);
+ gpr_strvec_add(buf, gpr_strdup("\n"));
}
-
- *p = 0;
- return buffer;
}
static void fail_no_event_received(cq_verifier *v) {
- char *expectations = expectations_to_string(v);
- gpr_log(GPR_ERROR, "no event received, but expected:\n%s", expectations);
- gpr_free(expectations);
+ gpr_strvec buf;
+ char *msg;
+ gpr_strvec_init(&buf);
+ gpr_strvec_add(&buf, gpr_strdup("no event received, but expected:\n"));
+ expectations_to_strvec(&buf, v);
+ msg = gpr_strvec_flatten(&buf, NULL);
+ gpr_log(GPR_ERROR, "%s", msg);
+ gpr_strvec_destroy(&buf);
+ gpr_free(msg);
abort();
}
@@ -333,9 +324,10 @@ void cq_verify(cq_verifier *v) {
gpr_time_add(gpr_now(), gpr_time_from_micros(10 * GPR_US_PER_SEC));
grpc_event *ev;
expectation *e;
+ char *s;
+ gpr_strvec have_tags;
- char have_tags[512] = {0};
- char *phave = have_tags;
+ gpr_strvec_init(&have_tags);
while (v->expect.next != &v->expect) {
ev = grpc_completion_queue_next(v->cq, deadline);
@@ -344,7 +336,8 @@ void cq_verify(cq_verifier *v) {
}
for (e = v->expect.next; e != &v->expect; e = e->next) {
- phave += sprintf(phave, " %p", e->tag);
+ gpr_asprintf(&s, " %p", e->tag);
+ gpr_strvec_add(&have_tags, s);
if (e->tag == ev->tag) {
verify_matches(e, ev);
e->next->prev = e->prev;
@@ -354,15 +347,20 @@ void cq_verify(cq_verifier *v) {
}
}
if (e == &v->expect) {
- char *s = grpc_event_string(ev);
+ s = grpc_event_string(ev);
gpr_log(GPR_ERROR, "event not found: %s", s);
- gpr_log(GPR_ERROR, "have tags:%s", have_tags);
gpr_free(s);
+ s = gpr_strvec_flatten(&have_tags, NULL);
+ gpr_log(GPR_ERROR, "have tags:%s", s);
+ gpr_free(s);
+ gpr_strvec_destroy(&have_tags);
abort();
}
grpc_event_finish(ev);
}
+
+ gpr_strvec_destroy(&have_tags);
}
void cq_verify_empty(cq_verifier *v) {
diff --git a/test/core/end2end/tests/census_simple_request.c b/test/core/end2end/tests/census_simple_request.c
index 719f0fe662..86cef437be 100644
--- a/test/core/end2end/tests/census_simple_request.c
+++ b/test/core/end2end/tests/census_simple_request.c
@@ -37,6 +37,7 @@
#include <string.h>
#include <unistd.h>
+#include "src/core/support/string.h"
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@@ -145,7 +146,7 @@ static void test_body(grpc_end2end_test_fixture f) {
static void test_invoke_request_with_census(
grpc_end2end_test_config config, const char *name,
void (*body)(grpc_end2end_test_fixture f)) {
- char fullname[64];
+ char *fullname;
grpc_end2end_test_fixture f;
grpc_arg client_arg, server_arg;
grpc_channel_args client_args, server_args;
@@ -163,11 +164,12 @@ static void test_invoke_request_with_census(
server_args.num_args = 1;
server_args.args = &server_arg;
- sprintf(fullname, "%s/%s", __FUNCTION__, name);
+ gpr_asprintf(&fullname, "%s/%s", __FUNCTION__, name);
f = begin_test(config, fullname, &client_args, &server_args);
body(f);
end_test(&f);
config.tear_down_data(&f);
+ gpr_free(fullname);
}
void grpc_end2end_tests(grpc_end2end_test_config config) {
diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c
index 23fc201d84..f8894a8ba9 100644
--- a/test/core/end2end/tests/simple_request.c
+++ b/test/core/end2end/tests/simple_request.c
@@ -37,6 +37,7 @@
#include <string.h>
#include <unistd.h>
+#include "src/core/support/string.h"
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@@ -198,15 +199,16 @@ static void simple_request_body2(grpc_end2end_test_fixture f) {
static void test_invoke_simple_request(
grpc_end2end_test_config config, const char *name,
void (*body)(grpc_end2end_test_fixture f)) {
- char fullname[64];
+ char *fullname;
grpc_end2end_test_fixture f;
- sprintf(fullname, "%s/%s", __FUNCTION__, name);
+ gpr_asprintf(&fullname, "%s/%s", __FUNCTION__, name);
f = begin_test(config, fullname, NULL, NULL);
body(f);
end_test(&f);
config.tear_down_data(&f);
+ gpr_free(fullname);
}
static void test_invoke_10_simple_requests(grpc_end2end_test_config config) {
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index ec21e0d42f..1c83cc8059 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -498,10 +498,8 @@ static void validate_service_account_http_request(
char *expected_body = NULL;
GPR_ASSERT(body != NULL);
GPR_ASSERT(body_size != 0);
- expected_body = gpr_malloc(strlen(expected_service_account_http_body_prefix) +
- strlen(test_signed_jwt) + 1);
- sprintf(expected_body, "%s%s", expected_service_account_http_body_prefix,
- test_signed_jwt);
+ gpr_asprintf(&expected_body, "%s%s",
+ expected_service_account_http_body_prefix, test_signed_jwt);
GPR_ASSERT(strlen(expected_body) == body_size);
GPR_ASSERT(!memcmp(expected_body, body, body_size));
gpr_free(expected_body);
diff --git a/test/core/statistics/hash_table_test.c b/test/core/statistics/hash_table_test.c
index ebfc2a2a9a..f8df2574a4 100644
--- a/test/core/statistics/hash_table_test.c
+++ b/test/core/statistics/hash_table_test.c
@@ -38,6 +38,7 @@
#include "src/core/statistics/hash_table.h"
#include "src/core/support/murmur_hash.h"
+#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
@@ -187,15 +188,15 @@ static void test_insertion_and_deletion_with_high_collision_rate(void) {
census_ht_option opt = {CENSUS_HT_POINTER, 13, &force_collision,
&cmp_str_keys, NULL, NULL};
census_ht* ht = census_ht_create(&opt);
- char key_str[1000][10];
+ char key_str[1000][GPR_LTOA_MIN_BUFSIZE];
gpr_uint64 val = 0;
int i = 0;
for (i = 0; i < 1000; i++) {
census_ht_key key;
key.ptr = key_str[i];
- sprintf(key_str[i], "%d", i);
+ gpr_ltoa(i, key_str[i]);
census_ht_insert(ht, key, (void*)(&val));
- printf("%d\n", i);
+ gpr_log(GPR_INFO, "%d\n", i);
GPR_ASSERT(census_ht_get_size(ht) == (i + 1));
}
for (i = 0; i < 1000; i++) {
diff --git a/test/core/transport/chttp2/hpack_table_test.c b/test/core/transport/chttp2/hpack_table_test.c
index 1576a30c1b..d155dee9dc 100644
--- a/test/core/transport/chttp2/hpack_table_test.c
+++ b/test/core/transport/chttp2/hpack_table_test.c
@@ -36,6 +36,7 @@
#include <string.h>
#include <stdio.h>
+#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "test/core/util/test_config.h"
@@ -131,8 +132,8 @@ static void test_static_lookup(void) {
static void test_many_additions(void) {
grpc_chttp2_hptbl tbl;
int i;
- char key[32];
- char value[32];
+ char *key;
+ char *value;
grpc_mdctx *mdctx;
LOG_TEST();
@@ -141,14 +142,18 @@ static void test_many_additions(void) {
grpc_chttp2_hptbl_init(&tbl, mdctx);
for (i = 0; i < 1000000; i++) {
- sprintf(key, "K:%d", i);
- sprintf(value, "VALUE:%d", i);
+ gpr_asprintf(&key, "K:%d", i);
+ gpr_asprintf(&value, "VALUE:%d", i);
grpc_chttp2_hptbl_add(&tbl, grpc_mdelem_from_strings(mdctx, key, value));
assert_index(&tbl, 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value);
+ gpr_free(key);
+ gpr_free(value);
if (i) {
- sprintf(key, "K:%d", i - 1);
- sprintf(value, "VALUE:%d", i - 1);
+ gpr_asprintf(&key, "K:%d", i - 1);
+ gpr_asprintf(&value, "VALUE:%d", i - 1);
assert_index(&tbl, 2 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value);
+ gpr_free(key);
+ gpr_free(value);
}
}
@@ -226,7 +231,7 @@ static void test_find(void) {
/* overflow the string buffer, check find still works */
for (i = 0; i < 10000; i++) {
- sprintf(buffer, "%d", i);
+ gpr_ltoa(i, buffer);
grpc_chttp2_hptbl_add(&tbl,
grpc_mdelem_from_strings(mdctx, "test", buffer));
}
@@ -245,7 +250,7 @@ static void test_find(void) {
for (i = 0; i < tbl.num_ents; i++) {
int expect = 9999 - i;
- sprintf(buffer, "%d", expect);
+ gpr_ltoa(expect, buffer);
r = find_simple(&tbl, "test", buffer);
GPR_ASSERT(r.index == i + 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY);
diff --git a/test/core/transport/chttp2/stream_encoder_test.c b/test/core/transport/chttp2/stream_encoder_test.c
index eb0f688f58..5e8ec0a1af 100644
--- a/test/core/transport/chttp2/stream_encoder_test.c
+++ b/test/core/transport/chttp2/stream_encoder_test.c
@@ -186,7 +186,7 @@ static void encode_int_to_str(int i, char *p) {
static void test_decode_table_overflow(void) {
int i;
char key[3], value[3];
- char expect[128];
+ char *expect;
for (i = 0; i < 114; i++) {
if (i > 0) {
@@ -197,18 +197,21 @@ static void test_decode_table_overflow(void) {
encode_int_to_str(i + 1, value);
if (i + 61 >= 127) {
- sprintf(expect, "000009 0104 deadbeef ff%02x 40 02%02x%02x 02%02x%02x",
- i + 61 - 127, key[0], key[1], value[0], value[1]);
+ gpr_asprintf(&expect,
+ "000009 0104 deadbeef ff%02x 40 02%02x%02x 02%02x%02x",
+ i + 61 - 127, key[0], key[1], value[0], value[1]);
} else if (i > 0) {
- sprintf(expect, "000008 0104 deadbeef %02x 40 02%02x%02x 02%02x%02x",
- 0x80 + 61 + i, key[0], key[1], value[0], value[1]);
+ gpr_asprintf(&expect,
+ "000008 0104 deadbeef %02x 40 02%02x%02x 02%02x%02x",
+ 0x80 + 61 + i, key[0], key[1], value[0], value[1]);
} else {
- sprintf(expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x", key[0],
- key[1], value[0], value[1]);
+ gpr_asprintf(&expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x",
+ key[0], key[1], value[0], value[1]);
}
add_sopb_header(key, value);
verify_sopb(0, 0, 0, expect);
+ gpr_free(expect);
}
/* if the above passes, then we must have just knocked this pair out of the
diff --git a/test/core/transport/chttp2/timeout_encoding_test.c b/test/core/transport/chttp2/timeout_encoding_test.c
index ffa0070e34..0ad90dbcef 100644
--- a/test/core/transport/chttp2/timeout_encoding_test.c
+++ b/test/core/transport/chttp2/timeout_encoding_test.c
@@ -36,6 +36,8 @@
#include <stdio.h>
#include <string.h>
+#include "src/core/support/string.h"
+#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
#include "test/core/util/test_config.h"
@@ -93,16 +95,23 @@ void decode_suite(char ext, gpr_timespec (*answer)(long x)) {
1234567, 12345678, 123456789, 98765432, 9876543, 987654,
98765, 9876, 987, 98, 9};
int i;
- char input[32];
+ char *input;
for (i = 0; i < GPR_ARRAY_SIZE(test_vals); i++) {
- sprintf(input, "%ld%c", test_vals[i], ext);
+ gpr_asprintf(&input, "%ld%c", test_vals[i], ext);
assert_decodes_as(input, answer(test_vals[i]));
- sprintf(input, " %ld%c", test_vals[i], ext);
+ gpr_free(input);
+
+ gpr_asprintf(&input, " %ld%c", test_vals[i], ext);
assert_decodes_as(input, answer(test_vals[i]));
- sprintf(input, "%ld %c", test_vals[i], ext);
+ gpr_free(input);
+
+ gpr_asprintf(&input, "%ld %c", test_vals[i], ext);
assert_decodes_as(input, answer(test_vals[i]));
- sprintf(input, "%ld %c ", test_vals[i], ext);
+ gpr_free(input);
+
+ gpr_asprintf(&input, "%ld %c ", test_vals[i], ext);
assert_decodes_as(input, answer(test_vals[i]));
+ gpr_free(input);
}
}
diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c
index 804096d0e1..b23db894be 100644
--- a/test/core/transport/metadata_test.c
+++ b/test/core/transport/metadata_test.c
@@ -35,6 +35,7 @@
#include <stdio.h>
+#include "src/core/support/string.h"
#include "src/core/transport/chttp2/bin_encoder.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@@ -99,7 +100,7 @@ static void test_create_metadata(void) {
static void test_create_many_ephemeral_metadata(void) {
grpc_mdctx *ctx;
- char buffer[256];
+ char buffer[GPR_LTOA_MIN_BUFSIZE];
long i;
size_t mdtab_capacity_before;
@@ -109,7 +110,7 @@ static void test_create_many_ephemeral_metadata(void) {
mdtab_capacity_before = grpc_mdctx_get_mdtab_capacity_test_only(ctx);
/* add, and immediately delete a bunch of different elements */
for (i = 0; i < MANY; i++) {
- sprintf(buffer, "%ld", i);
+ gpr_ltoa(i, buffer);
grpc_mdelem_unref(grpc_mdelem_from_strings(ctx, "a", buffer));
}
/* capacity should not grow */
@@ -120,7 +121,7 @@ static void test_create_many_ephemeral_metadata(void) {
static void test_create_many_persistant_metadata(void) {
grpc_mdctx *ctx;
- char buffer[256];
+ char buffer[GPR_LTOA_MIN_BUFSIZE];
long i;
grpc_mdelem **created = gpr_malloc(sizeof(grpc_mdelem *) * MANY);
grpc_mdelem *md;
@@ -130,12 +131,12 @@ static void test_create_many_persistant_metadata(void) {
ctx = grpc_mdctx_create();
/* add phase */
for (i = 0; i < MANY; i++) {
- sprintf(buffer, "%ld", i);
+ gpr_ltoa(i, buffer);
created[i] = grpc_mdelem_from_strings(ctx, "a", buffer);
}
/* verify phase */
for (i = 0; i < MANY; i++) {
- sprintf(buffer, "%ld", i);
+ gpr_ltoa(i, buffer);
md = grpc_mdelem_from_strings(ctx, "a", buffer);
GPR_ASSERT(md == created[i]);
grpc_mdelem_unref(md);
@@ -176,7 +177,7 @@ static void test_spin_creating_the_same_thing(void) {
static void test_things_stick_around(void) {
grpc_mdctx *ctx;
int i, j;
- char buffer[64];
+ char *buffer;
int nstrs = 10000;
grpc_mdstr **strs = gpr_malloc(sizeof(grpc_mdstr *) * nstrs);
int *shuf = gpr_malloc(sizeof(int) * nstrs);
@@ -187,9 +188,10 @@ static void test_things_stick_around(void) {
ctx = grpc_mdctx_create();
for (i = 0; i < nstrs; i++) {
- sprintf(buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", i);
+ gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", i);
strs[i] = grpc_mdstr_from_string(ctx, buffer);
shuf[i] = i;
+ gpr_free(buffer);
}
for (i = 0; i < nstrs; i++) {
@@ -208,10 +210,11 @@ static void test_things_stick_around(void) {
for (i = 0; i < nstrs; i++) {
grpc_mdstr_unref(strs[shuf[i]]);
for (j = i + 1; j < nstrs; j++) {
- sprintf(buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", shuf[j]);
+ gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", shuf[j]);
test = grpc_mdstr_from_string(ctx, buffer);
GPR_ASSERT(test == strs[shuf[j]]);
grpc_mdstr_unref(test);
+ gpr_free(buffer);
}
}
diff --git a/tools/clang-format/clang-format-all.sh b/tools/clang-format/clang-format-all.sh
deleted file mode 100755
index 62228b0b01..0000000000
--- a/tools/clang-format/clang-format-all.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-set -e
-source $(dirname $0)/config.sh
-cd $(dirname $0)/../..
-for dir in src test include
-do
- find $dir -name '*.c' -or -name '*.cc' -or -name '*.h' | xargs $CLANG_FORMAT -i
-done
-
diff --git a/tools/clang-format/config.sh b/tools/clang-format/config.sh
deleted file mode 100644
index 3adf2678e7..0000000000
--- a/tools/clang-format/config.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-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
-
diff --git a/tools/dockerfile/grpc_java/Dockerfile b/tools/dockerfile/grpc_java/Dockerfile
index 78659dedeb..f234f514e6 100644
--- a/tools/dockerfile/grpc_java/Dockerfile
+++ b/tools/dockerfile/grpc_java/Dockerfile
@@ -1,9 +1,6 @@
# Dockerfile for the gRPC Java dev image
FROM grpc/java_base
-# Start the daemon that allows access to private git-on-borg repos
-RUN /var/local/git/gcompute-tools/git-cookie-authdaemon
-
RUN cd /var/local/git/grpc-java/lib/okhttp && \
mvn -pl okhttp -am install
RUN cd /var/local/git/grpc-java/lib/netty && \
@@ -13,4 +10,4 @@ RUN cd /var/local/git/grpc-java && \
mvn install
# Specify the default command such that the interop server runs on its known testing port
-CMD ["/var/local/git/grpc-java/run-test-server.sh", "--transport=HTTP2_NETTY_TLS", "--grpc_version=2", "--port=8030"]
+CMD ["/var/local/git/grpc-java/run-test-server.sh", "--use_tls=true", "--port=8030"]
diff --git a/tools/dockerfile/grpc_java_base/Dockerfile b/tools/dockerfile/grpc_java_base/Dockerfile
index 44fa52c0e8..3271d1b2c2 100644
--- a/tools/dockerfile/grpc_java_base/Dockerfile
+++ b/tools/dockerfile/grpc_java_base/Dockerfile
@@ -20,14 +20,24 @@ ENV M2_HOME /var/local/apache-maven-3.2.1
ENV PATH $PATH:$JAVA_HOME/bin:$M2_HOME/bin
ENV LD_LIBRARY_PATH /usr/local/lib
-# Start the daemon that allows access to the protected git-on-borg repos
-RUN /var/local/git/gcompute-tools/git-cookie-authdaemon
+# Install a GitHub SSH service credential that gives access to the GitHub repo while it's private
+# TODO: remove this once the repo is public
+ADD .ssh .ssh
+RUN chmod 600 .ssh/github.rsa
+RUN mkdir -p $HOME/.ssh && echo 'Host github.com' > $HOME/.ssh/config
+RUN echo " IdentityFile /.ssh/github.rsa" >> $HOME/.ssh/config
+RUN echo 'StrictHostKeyChecking no' >> $HOME/.ssh/config
-RUN git clone --recursive https://team.googlesource.com/one-platform-grpc-team/grpc-java /var/local/git/grpc-java
+# Get the protobuf source from GitHub and install it
+RUN git clone --recursive --branch v2.6.1 git@github.com:google/protobuf.git /var/local/git/protobuf
+RUN cd /var/local/git/protobuf && \
+ ./autogen.sh && \
+ ./configure --prefix=/usr && \
+ make -j12 && make check && make install && make clean
RUN cd /var/local/git/grpc-java/lib/okhttp && \
mvn -pl okhttp -am validate
RUN cd /var/local/git/grpc-java/lib/netty && \
mvn -pl codec-http2 -am validate
RUN cd /var/local/git/grpc-java && \
- mvn validate \ No newline at end of file
+ mvn validate
diff --git a/tools/dockerfile/grpc_ruby/Dockerfile b/tools/dockerfile/grpc_ruby/Dockerfile
index c677ceffff..f01f81d539 100644
--- a/tools/dockerfile/grpc_ruby/Dockerfile
+++ b/tools/dockerfile/grpc_ruby/Dockerfile
@@ -6,6 +6,9 @@ RUN cd /var/local/git/grpc \
&& git pull --recurse-submodules \
&& git submodule update --init --recursive
+# TODO: remove this, once make install is fixed
+RUN touch /var/local/git/grpc/include/grpc/support/string.h
+
# Build the C core.
RUN make install_c -C /var/local/git/grpc
@@ -18,5 +21,8 @@ RUN /bin/bash -l -c 'cd /var/local/git/grpc/src/ruby && bundle && rake compile:g
# - however, the interop server and client run OK, so this bug can be investigated
# RUN /bin/bash -l -c 'cd /var/local/git/grpc/src/ruby && bundle && rake'
+# Add a cacerts directory containing the Google root pem file, allowing the ruby client to access the production test instance
+ADD cacerts cacerts
+
# Specify the default command such that the interop server runs on its known testing port
-CMD ["/bin/bash", "-l", "-c", "ruby /var/local/git/grpc/src/ruby/bin/interop/interop_server.rb --port 8060"]
+CMD ["/bin/bash", "-l", "-c", "ruby /var/local/git/grpc/src/ruby/bin/interop/interop_server.rb --use_tls --port 8060"]
diff --git a/tools/gce_setup/cloud_prod_runner.sh b/tools/gce_setup/cloud_prod_runner.sh
new file mode 100755
index 0000000000..0c1163ad7d
--- /dev/null
+++ b/tools/gce_setup/cloud_prod_runner.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+main() {
+ source grpc_docker.sh
+ test_cases=(large_unary empty_unary client_streaming server_streaming)
+ clients=(cxx java go ruby)
+ for test_case in "${test_cases[@]}"
+ do
+ for client in "${clients[@]}"
+ do
+ if grpc_cloud_prod_test $test_case grpc-docker-testclients $client
+ then
+ echo "$test_case $client $server passed" >> /tmp/cloud_prod_result.txt
+ else
+ echo "$test_case $client $server failed" >> /tmp/cloud_prod_result.txt
+ fi
+ done
+ done
+ gsutil cp /tmp/cloud_prod_result.txt gs://stoked-keyword-656-output/cloud_prod_result.txt
+ rm /tmp/cloud_prod_result.txt
+}
+
+set -x
+main "$@"
diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh
index 145685305c..16d6ef40e3 100755
--- a/tools/gce_setup/grpc_docker.sh
+++ b/tools/gce_setup/grpc_docker.sh
@@ -393,6 +393,53 @@ grpc_interop_test_args() {
}
}
+# checks the positional args and assigns them to variables visible in the caller
+#
+# these are the positional args passed to grpc_cloud_prod_test after option flags
+# are removed
+#
+# three args are expected, in order
+# - test_case
+# - host <the gce docker instance on which to run the test>
+# - client to run
+grpc_cloud_prod_test_args() {
+ [[ -n $1 ]] && { # test_case
+ test_case=$1
+ shift
+ } || {
+ echo "$FUNCNAME: missing arg: test_case" 1>&2
+ return 1
+ }
+
+ [[ -n $1 ]] && { # host
+ host=$1
+ shift
+ } || {
+ echo "$FUNCNAME: missing arg: host" 1>&2
+ return 1
+ }
+
+ [[ -n $1 ]] && { # client_type
+ case $1 in
+ cxx|go|java|nodejs|php|python|ruby)
+ grpc_gen_test_cmd="grpc_cloud_prod_gen_$1_cmd"
+ declare -F $grpc_gen_test_cmd >> /dev/null || {
+ echo "-f: test_func for $1 => $grpc_gen_test_cmd is not defined" 1>&2
+ return 2
+ }
+ shift
+ ;;
+ *)
+ echo "bad client_type: $1" 1>&2
+ return 1
+ ;;
+ esac
+ } || {
+ echo "$FUNCNAME: missing arg: client_type" 1>&2
+ return 1
+ }
+}
+
_grpc_sync_scripts_args() {
grpc_gce_script_root='tools/gce_setup'
@@ -622,6 +669,52 @@ grpc_interop_test() {
gcloud compute $project_opt ssh $zone_opt $host --command "$cmd"
}
+# Runs a test command on a docker instance.
+#
+# call-seq:
+# grpc_cloud_prod_test <test_name> <host> <client_type>
+#
+# requirements:
+# host is a GCE instance running docker with access to the gRPC docker images
+# test_name is one of the named gRPC tests [http://go/grpc_interop_tests]
+# client_type is one of [cxx,go,java,php,python,ruby]
+#
+# it assumes:
+# that each grpc-imp has a docker image named grpc/<imp>, e.g, grpc/java
+# a test is run using $ docker run 'path/to/interop_test_bin --flags'
+# the required images are available on <host>
+#
+# each client_type should have an associated bash func:
+# grpc_cloud_prod_gen_<client_type>_cmd
+# the func provides the dockerized commmand for running client_type's test.
+# If no such func is available, tests for that client type cannot be run.
+grpc_cloud_prod_test() {
+ _grpc_ensure_gcloud_ssh || return 1;
+ # declare vars local so that they don't pollute the shell environment
+ # where they this func is used.
+
+ local grpc_zone grpc_project dry_run # set by _grpc_set_project_and_zone
+ # grpc_cloud_prod_test_args
+ local test_case host grpc_gen_test_cmd
+
+ # set the project zone and check that all necessary args are provided
+ _grpc_set_project_and_zone -f grpc_cloud_prod_test_args "$@" || return 1
+ gce_has_instance $grpc_project $host || return 1;
+
+ local test_case_flag=" --test_case=$test_case"
+ cmd=$($grpc_gen_test_cmd $test_case_flag)
+ [[ -n $cmd ]] || return 1
+
+ local project_opt="--project $grpc_project"
+ local zone_opt="--zone $grpc_zone"
+ local ssh_cmd="bash -l -c \"$cmd\""
+ echo "will run:"
+ echo " $ssh_cmd"
+ echo "on $host"
+ [[ $dry_run == 1 ]] && return 0 # don't run the command on a dry run
+ gcloud compute $project_opt ssh $zone_opt $host --command "$cmd"
+}
+
# constructs the full dockerized ruby interop test cmd.
#
# call-seq:
@@ -630,10 +723,27 @@ grpc_interop_test() {
grpc_interop_gen_ruby_cmd() {
local cmd_prefix="sudo docker run grpc/ruby bin/bash -l -c"
local test_script="/var/local/git/grpc/src/ruby/bin/interop/interop_client.rb"
- local the_cmd="$cmd_prefix 'ruby $test_script $@'"
+ local the_cmd="$cmd_prefix 'ruby $test_script --use_test_ca --use_tls $@'"
+ echo $the_cmd
+}
+
+
+# constructs the full dockerized java interop test cmd.
+#
+# call-seq:
+# flags= .... # generic flags to include the command
+# cmd=$($grpc_gen_test_cmd $flags)
+grpc_cloud_prod_gen_ruby_cmd() {
+ local cmd_prefix="sudo docker run grpc/ruby bin/bash -l -c"
+ local test_script="/var/local/git/grpc/src/ruby/bin/interop/interop_client.rb"
+ local test_script+=" --use_tls"
+ local gfe_flags=" --server_port=443 --server_host=grpc-test.sandbox.google.com --server_host_override=grpc-test.sandbox.google.com"
+ local env_prefix="SSL_CERT_FILE=/cacerts/roots.pem"
+ local the_cmd="$cmd_prefix '$env_prefix ruby $test_script $gfe_flags $@'"
echo $the_cmd
}
+
# constructs the full dockerized Go interop test cmd.
#
# call-seq:
@@ -655,11 +765,25 @@ grpc_interop_gen_go_cmd() {
grpc_interop_gen_java_cmd() {
local cmd_prefix="sudo docker run grpc/java";
local test_script="/var/local/git/grpc-java/run-test-client.sh";
- local test_script+=" --transport=NETTY_TLS --grpc_version=2"
+ local test_script+=" --server_host_override=foo.test.google.fr --use_test_ca=true --use_tls=true"
local the_cmd="$cmd_prefix $test_script $@";
echo $the_cmd
}
+# constructs the full dockerized java interop test cmd.
+#
+# call-seq:
+# flags= .... # generic flags to include the command
+# cmd=$($grpc_gen_test_cmd $flags)
+grpc_cloud_prod_gen_java_cmd() {
+ local cmd_prefix="sudo docker run grpc/java";
+ local test_script="/var/local/git/grpc-java/run-test-client.sh";
+ local test_script+=" --use_tls=true"
+ local gfe_flags=" --server_port=443 --server_host=grpc-test.sandbox.google.com --server_host_override=grpc-test.sandbox.google.com"
+ local the_cmd="$cmd_prefix $test_script $gfe_flags $@";
+ echo $the_cmd
+}
+
# constructs the full dockerized php interop test cmd.
#
# TODO(mlumish): update this to use the script once that's on git-on-borg
@@ -683,10 +807,24 @@ grpc_interop_gen_php_cmd() {
# flags= .... # generic flags to include the command
# cmd=$($grpc_gen_test_cmd $flags)
grpc_interop_gen_cxx_cmd() {
- local cmd_prefix="sudo docker run grpc/cxx";
+ local cmd_prefix="sudo docker run grpc/cxx";
local test_script="/var/local/git/grpc/bins/opt/interop_client --enable_ssl";
local the_cmd="$cmd_prefix $test_script $@";
echo $the_cmd
}
+# constructs the full dockerized cpp interop test cmd.
+#
+#
+# call-seq:
+# flags= .... # generic flags to include the command
+# cmd=$($grpc_gen_test_cmd $flags)
+grpc_cloud_prod_gen_cxx_cmd() {
+ local cmd_prefix="sudo docker run grpc/cxx";
+ local test_script="/var/local/git/grpc/bins/opt/interop_client --enable_ssl";
+ local gfe_flags=" --use_prod_roots --server_port=443 --server_host=grpc-test.sandbox.google.com --server_host_override=grpc-test.sandbox.google.com"
+ local the_cmd="$cmd_prefix $test_script $gfe_flags $@";
+ echo $the_cmd
+}
+
# TODO(grpc-team): add grpc_interop_gen_xxx_cmd for python|cxx|nodejs
diff --git a/tools/gce_setup/interop_test_runner.sh b/tools/gce_setup/interop_test_runner.sh
new file mode 100755
index 0000000000..1c0d82095c
--- /dev/null
+++ b/tools/gce_setup/interop_test_runner.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+main() {
+ source grpc_docker.sh
+ test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming)
+ clients=(cxx java go ruby)
+ servers=(cxx java go ruby)
+ for test_case in "${test_cases[@]}"
+ do
+ for client in "${clients[@]}"
+ do
+ for server in "${servers[@]}"
+ do
+ if grpc_interop_test $test_case grpc-docker-testclients $client grpc-docker-server $server
+ then
+ echo "$test_case $client $server passed" >> /tmp/interop_result.txt
+ else
+ echo "$test_case $client $server failed" >> /tmp/interop_result.txt
+ fi
+ done
+ done
+ done
+ gsutil cp /tmp/interop_result.txt gs://stoked-keyword-656-output/interop_result.txt
+ rm /tmp/interop_result.txt
+}
+
+set -x
+main "$@"
diff --git a/tools/gce_setup/shared_startup_funcs.sh b/tools/gce_setup/shared_startup_funcs.sh
index f1dbca9a2e..69f6ba8cc0 100755
--- a/tools/gce_setup/shared_startup_funcs.sh
+++ b/tools/gce_setup/shared_startup_funcs.sh
@@ -405,14 +405,18 @@ grpc_dockerfile_install() {
# For specific base images, sync the ssh key into the .ssh dir in the dockerfile context
[[ $image_label == "grpc/base" ]] && {
- grpc_docker_sync_github_key $dockerfile_dir/.ssh 'base_ssh_key'|| return 1;
+ grpc_docker_sync_github_key $dockerfile_dir/.ssh 'base_ssh_key' || return 1;
}
[[ $image_label == "grpc/go" ]] && {
- grpc_docker_sync_github_key $dockerfile_dir/.ssh 'go_ssh_key'|| return 1;
+ grpc_docker_sync_github_key $dockerfile_dir/.ssh 'go_ssh_key' || return 1;
}
[[ $image_label == "grpc/java_base" ]] && {
- grpc_docker_sync_github_key $dockerfile_dir/.ssh 'java_base_ssh_key'|| return 1;
+ grpc_docker_sync_github_key $dockerfile_dir/.ssh 'java_base_ssh_key' || return 1;
}
+ [[ $image_label == "grpc/ruby" ]] && {
+ grpc_docker_sync_roots_pem $dockerfile_dir/cacerts || return 1;
+ }
+
# TODO(temiola): maybe make cache/no-cache a func option?
sudo docker build $cache_opt -t $image_label $dockerfile_dir || {
@@ -471,3 +475,31 @@ grpc_docker_sync_github_key() {
}
gsutil cp $src $gcs_key_path $local_key_path
}
+
+# grpc_docker_sync_roots_pem.
+#
+# Copies the root pems from GCS to the target dir
+#
+# call-seq:
+# grpc_docker_sync_roots_pem <target_dir>
+grpc_docker_sync_roots_pem() {
+ local target_dir=$1
+ [[ -n $target_dir ]] || { echo "$FUNCNAME: missing arg: target_dir" >&2; return 1; }
+
+ # determine the admin root; the parent of the dockerfile root,
+ local gs_dockerfile_root=$(load_metadata "attributes/gs_dockerfile_root")
+ [[ -n $gs_dockerfile_root ]] || {
+ echo "$FUNCNAME: missing metadata: gs_dockerfile_root" >&2
+ return 1
+ }
+ local gcs_admin_root=$(dirname $gs_dockerfile_root)
+
+ # cp the file from gsutil to a known local area
+ local gcs_certs_path=$gcs_admin_root/cacerts/roots.pem
+ local local_certs_path=$target_dir/roots.pem
+ mkdir -p $target_dir || {
+ echo "$FUNCNAME: could not create dir: $target_dir" 1>&2
+ return 1
+ }
+ gsutil cp $src $gcs_certs_path $local_certs_path
+}
diff --git a/tools/run_tests/build_node.sh b/tools/run_tests/build_node.sh
index 600b1bde8c..4b092982b2 100755
--- a/tools/run_tests/build_node.sh
+++ b/tools/run_tests/build_node.sh
@@ -2,19 +2,18 @@
set -ex
+CONFIG=${CONFIG:-opt}
+
# change to grpc repo root
cd $(dirname $0)/../..
# tells npm install to look for files in that directory
export GRPC_ROOT=`pwd`
# tells npm install the subdirectory with library files
-export GRPC_LIB_SUBDIR=libs/opt
+export GRPC_LIB_SUBDIR=libs/$CONFIG
# tells npm install not to use default locations
export GRPC_NO_INSTALL=yes
-# build the c libraries
-make -j static_c
-
cd src/node
npm install
diff --git a/tools/run_tests/build_php.sh b/tools/run_tests/build_php.sh
index 6841656bdb..0a8d0c7492 100755
--- a/tools/run_tests/build_php.sh
+++ b/tools/run_tests/build_php.sh
@@ -2,14 +2,13 @@
set -ex
+CONFIG=${CONFIG:-opt}
+
# change to grpc repo root
cd $(dirname $0)/../..
root=`pwd`
-export GRPC_LIB_SUBDIR=libs/opt
-
-# make the libraries
-make -j static_c
+export GRPC_LIB_SUBDIR=libs/$CONFIG
# build php
cd src/php
@@ -18,4 +17,3 @@ cd ext/grpc
phpize
./configure --enable-grpc=$root
make
-
diff --git a/tools/run_tests/run_lcov.sh b/tools/run_tests/run_lcov.sh
index 6f22b0e8a4..068213a3d2 100755
--- a/tools/run_tests/run_lcov.sh
+++ b/tools/run_tests/run_lcov.sh
@@ -7,7 +7,7 @@ out=`realpath ${1:-coverage}`
root=`realpath $(dirname $0)/../..`
tmp=`mktemp`
cd $root
-tools/run_tests/run_tests.py -c gcov
+tools/run_tests/run_tests.py -c gcov -l c c++
lcov --capture --directory . --output-file $tmp
genhtml $tmp --output-directory $out
rm $tmp
diff --git a/tools/run_tests/run_node.sh b/tools/run_tests/run_node.sh
new file mode 100755
index 0000000000..0056295949
--- /dev/null
+++ b/tools/run_tests/run_node.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../..
+
+root=`pwd`
+
+$root/src/node/node_modules/mocha/bin/mocha $root/src/node/test
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index da849f04cb..b7248e524b 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -46,8 +46,8 @@ class CLanguage(object):
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
+ self.binaries = [tgt['name']
+ for tgt in js
if tgt['language'] == test_lang]
def test_binaries(self, config):
@@ -59,6 +59,19 @@ class CLanguage(object):
def build_steps(self):
return []
+class NodeLanguage(object):
+
+ def __init__(self):
+ self.allow_hashing = False
+
+ def test_binaries(self, config):
+ return ['tools/run_tests/run_node.sh']
+
+ def make_targets(self):
+ return ['static_c']
+
+ def build_steps(self):
+ return [['tools/run_tests/build_node.sh']]
class PhpLanguage(object):
@@ -69,7 +82,7 @@ class PhpLanguage(object):
return ['src/php/bin/run_tests.sh']
def make_targets(self):
- return []
+ return ['static_c']
def build_steps(self):
return [['tools/run_tests/build_php.sh']]
@@ -107,6 +120,7 @@ _DEFAULT = ['dbg', 'opt']
_LANGUAGES = {
'c++': CLanguage('cxx', 'c++'),
'c': CLanguage('c', 'c'),
+ 'node': NodeLanguage(),
'php': PhpLanguage(),
'python': PythonLanguage(),
}
@@ -190,8 +204,8 @@ class TestCache(object):
def _build_and_run(check_cancelled, newline_on_success, cache):
"""Do one pass of building & running tests."""
- # build latest, sharing cpu between the various makes
- if not jobset.run(build_steps):
+ # build latest sequentially
+ if not jobset.run(build_steps, maxjobs=1):
return 1
# run all the tests
diff --git a/vsprojects/vs2013/gpr.vcxproj b/vsprojects/vs2013/gpr.vcxproj
index 6075e25ca0..f71b586aff 100644
--- a/vsprojects/vs2013/gpr.vcxproj
+++ b/vsprojects/vs2013/gpr.vcxproj
@@ -86,7 +86,6 @@
<ClInclude Include="..\..\include\grpc\support\port_platform.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\sync.h" />
<ClInclude Include="..\..\include\grpc\support\sync_generic.h" />
<ClInclude Include="..\..\include\grpc\support\sync_posix.h" />
@@ -102,6 +101,7 @@
<ItemGroup>
<ClInclude Include="..\..\src\core\support\cpu.h" />
<ClInclude Include="..\..\src\core\support\murmur_hash.h" />
+ <ClInclude Include="..\..\src\core\support\string.h" />
<ClInclude Include="..\..\src\core\support\thd_internal.h" />
</ItemGroup>
<ItemGroup>
diff --git a/vsprojects/vs2013/gpr.vcxproj.filters b/vsprojects/vs2013/gpr.vcxproj.filters
index c1fccfff3b..013ed4b3c9 100644
--- a/vsprojects/vs2013/gpr.vcxproj.filters
+++ b/vsprojects/vs2013/gpr.vcxproj.filters
@@ -120,9 +120,6 @@
<ClInclude Include="..\..\include\grpc\support\slice_buffer.h">
<Filter>include\grpc\support</Filter>
</ClInclude>
- <ClInclude Include="..\..\include\grpc\support\string.h">
- <Filter>include\grpc\support</Filter>
- </ClInclude>
<ClInclude Include="..\..\include\grpc\support\sync.h">
<Filter>include\grpc\support</Filter>
</ClInclude>
@@ -164,6 +161,9 @@
<ClInclude Include="..\..\src\core\support\murmur_hash.h">
<Filter>src\core\support</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\core\support\string.h">
+ <Filter>src\core\support</Filter>
+ </ClInclude>
<ClInclude Include="..\..\src\core\support\thd_internal.h">
<Filter>src\core\support</Filter>
</ClInclude>