Merge pull request #4484 from alfatraining/fix_test/gpr_stack_lockfree_test
fix gpr_stack_lockfree_test assert bug on 64 bits
diff --git a/Makefile b/Makefile
index 02f1637..58a5011 100644
--- a/Makefile
+++ b/Makefile
@@ -1960,6 +1960,7 @@
connection_prefix_bad_client_test: $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test
headers_bad_client_test: $(BINDIR)/$(CONFIG)/headers_bad_client_test
initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
+server_registered_method_bad_client_test: $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test
simple_request_bad_client_test: $(BINDIR)/$(CONFIG)/simple_request_bad_client_test
unknown_frame_bad_client_test: $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test
bad_ssl_alpn_server: $(BINDIR)/$(CONFIG)/bad_ssl_alpn_server
@@ -3222,6 +3223,7 @@
$(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \
$(BINDIR)/$(CONFIG)/headers_bad_client_test \
$(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \
+ $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \
$(BINDIR)/$(CONFIG)/simple_request_bad_client_test \
$(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \
$(BINDIR)/$(CONFIG)/bad_ssl_alpn_server \
@@ -5540,6 +5542,8 @@
$(Q) $(BINDIR)/$(CONFIG)/headers_bad_client_test || ( echo test headers_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing initial_settings_frame_bad_client_test"
$(Q) $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test || ( echo test initial_settings_frame_bad_client_test failed ; exit 1 )
+ $(E) "[RUN] Testing server_registered_method_bad_client_test"
+ $(Q) $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test || ( echo test server_registered_method_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing simple_request_bad_client_test"
$(Q) $(BINDIR)/$(CONFIG)/simple_request_bad_client_test || ( echo test simple_request_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing unknown_frame_bad_client_test"
@@ -29229,6 +29233,23 @@
endif
+SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC = \
+ test/core/bad_client/tests/server_registered_method.c \
+
+SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC))))
+$(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test: $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LD) $(LDFLAGS) $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test
+
+$(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/server_registered_method.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+deps_server_registered_method_bad_client_test: $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_DEPS),true)
+-include $(SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_OBJS:.o=.dep)
+endif
+
+
SIMPLE_REQUEST_BAD_CLIENT_TEST_SRC = \
test/core/bad_client/tests/simple_request.c \
diff --git a/doc/PROTOCOL-HTTP2.md b/doc/PROTOCOL-HTTP2.md
index 7a26724..357ea72 100644
--- a/doc/PROTOCOL-HTTP2.md
+++ b/doc/PROTOCOL-HTTP2.md
@@ -45,7 +45,7 @@
* **Custom-Metadata** → Binary-Header / ASCII-Header
* **Binary-Header** → {Header-Name "-bin" } {_base64 encoded value_}
* **ASCII-Header** → Header-Name ASCII-Value
-* **Header-Name** → 1\*( %x30-39 / %x61-7A / "\_" / "-") ; 0-9 a-z \_ -
+* **Header-Name** → 1\*( %x30-39 / %x61-7A / "\_" / "-" / ".") ; 0-9 a-z \_ - .
* **ASCII-Value** → 1\*( %x20-%x7E ) ; space and printable ASCII
diff --git a/examples/cpp/helloworld/README.md b/examples/cpp/helloworld/README.md
index 7a7194d..90f3d6b 100644
--- a/examples/cpp/helloworld/README.md
+++ b/examples/cpp/helloworld/README.md
@@ -41,7 +41,7 @@
a greeting in a single `HelloReply`. This is the simplest type of RPC you
can specify in gRPC - we'll look at some other types later in this document.
-```
+```protobuf
syntax = "proto3";
option java_package = "ex.grpc";
@@ -93,20 +93,20 @@
channel can be created with the target address, credentials to use and
arguments as follows
- ```
+ ```cpp
auto channel = CreateChannel("localhost:50051", InsecureChannelCredentials());
```
- Create a stub. A stub implements the rpc methods of a service and in the
generated code, a method is provided to created a stub with a channel:
- ```
+ ```cpp
auto stub = helloworld::Greeter::NewStub(channel);
```
- Make a unary rpc, with `ClientContext` and request/response proto messages.
- ```
+ ```cpp
ClientContext context;
HelloRequest request;
request.set_name("hello");
@@ -116,7 +116,7 @@
- Check returned status and response.
- ```
+ ```cpp
if (status.ok()) {
// check reply.message()
} else {
@@ -130,7 +130,7 @@
- Implement the service interface
- ```
+ ```cpp
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
@@ -144,7 +144,7 @@
- Build a server exporting the service
- ```
+ ```cpp
GreeterServiceImpl service;
ServerBuilder builder;
builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials());
@@ -170,14 +170,14 @@
- Initiate the rpc and create a handle for the rpc. Bind the rpc to a
`CompletionQueue`.
- ```
+ ```cpp
CompletionQueue cq;
auto rpc = stub->AsyncSayHello(&context, request, &cq);
```
- Ask for reply and final status, with a unique tag
- ```
+ ```cpp
Status status;
rpc->Finish(&reply, &status, (void*)1);
```
@@ -185,7 +185,7 @@
- Wait for the completion queue to return the next tag. The reply and status are
ready once the tag passed into the corresponding `Finish()` call is returned.
- ```
+ ```cpp
void* got_tag;
bool ok = false;
cq.Next(&got_tag, &ok);
@@ -203,7 +203,7 @@
- Build a server exporting the async service
- ```
+ ```cpp
helloworld::Greeter::AsyncService service;
ServerBuilder builder;
builder.AddListeningPort("0.0.0.0:50051", InsecureServerCredentials());
@@ -214,7 +214,7 @@
- Request one rpc
- ```
+ ```cpp
ServerContext context;
HelloRequest request;
ServerAsyncResponseWriter<HelloReply> responder;
@@ -224,7 +224,7 @@
- Wait for the completion queue to return the tag. The context, request and
responder are ready once the tag is retrieved.
- ```
+ ```cpp
HelloReply reply;
Status status;
void* got_tag;
@@ -239,7 +239,7 @@
- Wait for the completion queue to return the tag. The rpc is finished when the
tag is back.
- ```
+ ```cpp
void* got_tag;
bool ok = false;
cq.Next(&got_tag, &ok);
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 5d064ef..55aad9e 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -974,11 +974,19 @@
batch_control *bctl = bctlp;
grpc_call *call = bctl->call;
- GPR_ASSERT(success);
- gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
- call->receiving_slice);
-
- continue_receiving_slices(exec_ctx, bctl);
+ if (success) {
+ gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
+ call->receiving_slice);
+ continue_receiving_slices(exec_ctx, bctl);
+ } else {
+ grpc_byte_stream_destroy(call->receiving_stream);
+ call->receiving_stream = NULL;
+ grpc_byte_buffer_destroy(*call->receiving_buffer);
+ *call->receiving_buffer = NULL;
+ if (gpr_unref(&bctl->steps_to_complete)) {
+ post_batch_completion(exec_ctx, bctl);
+ }
+ }
}
static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, int success) {
@@ -1119,11 +1127,12 @@
GRPC_CALL_INTERNAL_REF(call, "completion");
bctl->success = 1;
if (!is_notify_tag_closure) {
- grpc_cq_begin_op(call->cq);
+ grpc_cq_begin_op(call->cq, notify_tag);
}
gpr_mu_unlock(&call->mu);
post_batch_completion(exec_ctx, bctl);
- return GRPC_CALL_OK;
+ error = GRPC_CALL_OK;
+ goto done;
}
/* rewrite batch ops into a transport op */
@@ -1333,7 +1342,7 @@
GRPC_CALL_INTERNAL_REF(call, "completion");
if (!is_notify_tag_closure) {
- grpc_cq_begin_op(call->cq);
+ grpc_cq_begin_op(call->cq, notify_tag);
}
gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed);
diff --git a/src/core/surface/channel_connectivity.c b/src/core/surface/channel_connectivity.c
index 57529ff..10f5c4d 100644
--- a/src/core/surface/channel_connectivity.c
+++ b/src/core/surface/channel_connectivity.c
@@ -189,7 +189,7 @@
7, (channel, (int)last_observed_state, (long long)deadline.tv_sec,
(int)deadline.tv_nsec, (int)deadline.clock_type, cq, tag));
- grpc_cq_begin_op(cq);
+ grpc_cq_begin_op(cq, tag);
gpr_mu_init(&w->mu);
grpc_closure_init(&w->on_complete, watch_complete, w);
diff --git a/src/core/surface/channel_ping.c b/src/core/surface/channel_ping.c
index 1b6f06d..b4ce282 100644
--- a/src/core/surface/channel_ping.c
+++ b/src/core/surface/channel_ping.c
@@ -73,7 +73,7 @@
grpc_closure_init(&pr->closure, ping_done, pr);
op.send_ping = &pr->closure;
op.bind_pollset = grpc_cq_pollset(cq);
- grpc_cq_begin_op(cq);
+ grpc_cq_begin_op(cq, tag);
top_elem->filter->start_transport_op(&exec_ctx, top_elem, &op);
grpc_exec_ctx_finish(&exec_ctx);
}
diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c
index 7704a83..848a33a 100644
--- a/src/core/surface/completion_queue.c
+++ b/src/core/surface/completion_queue.c
@@ -73,6 +73,12 @@
plucker pluckers[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS];
grpc_closure pollset_shutdown_done;
+#ifndef NDEBUG
+ void **outstanding_tags;
+ size_t outstanding_tag_count;
+ size_t outstanding_tag_capacity;
+#endif
+
grpc_completion_queue *next_free;
};
@@ -89,6 +95,9 @@
while (g_freelist) {
grpc_completion_queue *next = g_freelist->next_free;
grpc_pollset_destroy(&g_freelist->pollset);
+#ifndef NDEBUG
+ gpr_free(g_freelist->outstanding_tags);
+#endif
gpr_free(g_freelist);
g_freelist = next;
}
@@ -117,6 +126,10 @@
cc = gpr_malloc(sizeof(grpc_completion_queue));
grpc_pollset_init(&cc->pollset);
+#ifndef NDEBUG
+ cc->outstanding_tags = NULL;
+ cc->outstanding_tag_capacity = 0;
+#endif
} else {
cc = g_freelist;
g_freelist = g_freelist->next_free;
@@ -134,6 +147,9 @@
cc->shutdown_called = 0;
cc->is_server_cq = 0;
cc->num_pluckers = 0;
+#ifndef NDEBUG
+ cc->outstanding_tag_count = 0;
+#endif
grpc_closure_init(&cc->pollset_shutdown_done, on_pollset_shutdown_done, cc);
GPR_TIMER_END("grpc_completion_queue_create", 0);
@@ -176,10 +192,17 @@
}
}
-void grpc_cq_begin_op(grpc_completion_queue *cc) {
+void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag) {
#ifndef NDEBUG
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
GPR_ASSERT(!cc->shutdown_called);
+ if (cc->outstanding_tag_count == cc->outstanding_tag_capacity) {
+ cc->outstanding_tag_capacity = GPR_MAX(4, 2 * cc->outstanding_tag_capacity);
+ cc->outstanding_tags =
+ gpr_realloc(cc->outstanding_tags, sizeof(*cc->outstanding_tags) *
+ cc->outstanding_tag_capacity);
+ }
+ cc->outstanding_tags[cc->outstanding_tag_count++] = tag;
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
#endif
gpr_ref(&cc->pending_events);
@@ -196,6 +219,9 @@
int shutdown;
int i;
grpc_pollset_worker *pluck_worker;
+#ifndef NDEBUG
+ int found = 0;
+#endif
GPR_TIMER_BEGIN("grpc_cq_end_op", 0);
@@ -206,6 +232,18 @@
((gpr_uintptr)&cc->completed_head) | ((gpr_uintptr)(success != 0));
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
+#ifndef NDEBUG
+ for (i = 0; i < (int)cc->outstanding_tag_count; i++) {
+ if (cc->outstanding_tags[i] == tag) {
+ cc->outstanding_tag_count--;
+ GPR_SWAP(void *, cc->outstanding_tags[i],
+ cc->outstanding_tags[cc->outstanding_tag_count]);
+ found = 1;
+ break;
+ }
+ }
+ GPR_ASSERT(found);
+#endif
shutdown = gpr_unref(&cc->pending_events);
if (!shutdown) {
cc->completed_tail->next =
diff --git a/src/core/surface/completion_queue.h b/src/core/surface/completion_queue.h
index a40bb04..1e40c48 100644
--- a/src/core/surface/completion_queue.h
+++ b/src/core/surface/completion_queue.h
@@ -68,10 +68,12 @@
#endif
/* Flag that an operation is beginning: the completion channel will not finish
- shutdown until a corrensponding grpc_cq_end_* call is made */
-void grpc_cq_begin_op(grpc_completion_queue *cc);
+ shutdown until a corrensponding grpc_cq_end_* call is made.
+ \a tag is currently used only in debug builds. */
+void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag);
-/* Queue a GRPC_OP_COMPLETED operation */
+/* Queue a GRPC_OP_COMPLETED operation; tag must correspond to the tag passed to
+ grpc_cq_begin_op */
void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
void *tag, int success,
void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
diff --git a/src/core/surface/server.c b/src/core/surface/server.c
index cdbd542..1e1cde3 100644
--- a/src/core/surface/server.c
+++ b/src/core/surface/server.c
@@ -1007,7 +1007,7 @@
/* lock, and gather up some stuff to do */
gpr_mu_lock(&server->mu_global);
- grpc_cq_begin_op(cq);
+ grpc_cq_begin_op(cq, tag);
if (server->shutdown_published) {
grpc_cq_end_op(&exec_ctx, cq, tag, 1, done_published_shutdown, NULL,
gpr_malloc(sizeof(grpc_cq_completion)));
@@ -1176,7 +1176,7 @@
error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
goto done;
}
- grpc_cq_begin_op(cq_for_notification);
+ grpc_cq_begin_op(cq_for_notification, tag);
details->reserved = NULL;
rc->type = BATCH_CALL;
rc->server = server;
@@ -1213,7 +1213,7 @@
error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
goto done;
}
- grpc_cq_begin_op(cq_for_notification);
+ grpc_cq_begin_op(cq_for_notification, tag);
rc->type = REGISTERED_CALL;
rc->server = server;
rc->tag = tag;
diff --git a/src/core/transport/chttp2/frame_data.c b/src/core/transport/chttp2/frame_data.c
index 732124b..60a3ce2 100644
--- a/src/core/transport/chttp2/frame_data.c
+++ b/src/core/transport/chttp2/frame_data.c
@@ -53,7 +53,8 @@
grpc_chttp2_data_parser *parser) {
grpc_byte_stream *bs;
if (parser->parsing_frame) {
- grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame);
+ grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame,
+ 0, 1);
}
while (
(bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) {
@@ -218,7 +219,8 @@
grpc_chttp2_incoming_byte_stream_push(
exec_ctx, p->parsing_frame,
gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
- grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame);
+ grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
+ 1);
p->parsing_frame = NULL;
p->state = GRPC_CHTTP2_DATA_FH_0;
return GRPC_CHTTP2_PARSE_OK;
@@ -227,7 +229,8 @@
exec_ctx, p->parsing_frame,
gpr_slice_sub(slice, (size_t)(cur - beg),
(size_t)(cur + p->frame_size - beg)));
- grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame);
+ grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
+ 1);
p->parsing_frame = NULL;
cur += p->frame_size;
goto fh_0; /* loop */
diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h
index fc35ea6..4ad9003 100644
--- a/src/core/transport/chttp2/internal.h
+++ b/src/core/transport/chttp2/internal.h
@@ -65,6 +65,7 @@
GRPC_CHTTP2_LIST_WRITTEN,
GRPC_CHTTP2_LIST_PARSING_SEEN,
GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
+ GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING,
GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT,
/** streams that are waiting to start because there are too many concurrent
streams on the connection */
@@ -151,6 +152,7 @@
grpc_byte_stream base;
gpr_refcount refs;
struct grpc_chttp2_incoming_byte_stream *next_message;
+ int failed;
grpc_chttp2_transport *transport;
grpc_chttp2_stream *stream;
@@ -391,8 +393,6 @@
gpr_uint8 write_closed;
/** is this stream reading half-closed (boolean) */
gpr_uint8 read_closed;
- /** is this stream finished closing (and reportably closed) */
- gpr_uint8 finished_close;
/** is this stream in the stream map? (boolean) */
gpr_uint8 in_stream_map;
/** has this stream seen an error? if 1, then pending incoming frames
@@ -586,6 +586,13 @@
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global);
+void grpc_chttp2_list_add_closed_waiting_for_writing(
+ grpc_chttp2_transport_global *transport_global,
+ grpc_chttp2_stream_global *stream_global);
+int grpc_chttp2_list_pop_closed_waiting_for_writing(
+ grpc_chttp2_transport_global *transport_global,
+ grpc_chttp2_stream_global **stream_global);
+
grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
@@ -742,7 +749,8 @@
grpc_chttp2_incoming_byte_stream *bs,
gpr_slice slice);
void grpc_chttp2_incoming_byte_stream_finished(
- grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs);
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
+ int from_parsing_thread);
void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *parsing,
diff --git a/src/core/transport/chttp2/stream_lists.c b/src/core/transport/chttp2/stream_lists.c
index a4c85b4..49f951d 100644
--- a/src/core/transport/chttp2/stream_lists.c
+++ b/src/core/transport/chttp2/stream_lists.c
@@ -353,6 +353,26 @@
return r;
}
+void grpc_chttp2_list_add_closed_waiting_for_writing(
+ grpc_chttp2_transport_global *transport_global,
+ grpc_chttp2_stream_global *stream_global) {
+ stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
+ STREAM_FROM_GLOBAL(stream_global),
+ GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING);
+}
+
+int grpc_chttp2_list_pop_closed_waiting_for_writing(
+ grpc_chttp2_transport_global *transport_global,
+ grpc_chttp2_stream_global **stream_global) {
+ grpc_chttp2_stream *stream;
+ int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
+ GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_WRITING);
+ if (r != 0) {
+ *stream_global = &stream->global;
+ }
+ return r;
+}
+
void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) {
stream_list_add_tail(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c
index 805d052..b5ca42d 100644
--- a/src/core/transport/chttp2/writing.c
+++ b/src/core/transport/chttp2/writing.c
@@ -332,17 +332,12 @@
while (grpc_chttp2_list_pop_written_stream(
transport_global, transport_writing, &stream_global, &stream_writing)) {
- if (stream_writing->sent_trailing_metadata) {
- grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
- !transport_global->is_client, 1);
- }
if (stream_writing->sent_initial_metadata) {
grpc_chttp2_complete_closure_step(
exec_ctx, &stream_global->send_initial_metadata_finished, 1);
}
if (stream_writing->sent_message) {
GPR_ASSERT(stream_writing->send_message == NULL);
- GPR_ASSERT(stream_global->send_message_finished);
grpc_chttp2_complete_closure_step(
exec_ctx, &stream_global->send_message_finished, 1);
stream_writing->sent_message = 0;
@@ -351,6 +346,10 @@
grpc_chttp2_complete_closure_step(
exec_ctx, &stream_global->send_trailing_metadata_finished, 1);
}
+ if (stream_writing->sent_trailing_metadata) {
+ grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
+ !transport_global->is_client, 1);
+ }
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
}
gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf);
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index aa459c8..c3847bb 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -134,6 +134,9 @@
static void check_read_ops(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global);
+static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
+ grpc_chttp2_stream_global *stream_global);
+
/*
* CONSTRUCTION/DESTRUCTION/REFCOUNTING
*/
@@ -625,6 +628,7 @@
void *transport_writing_ptr, int success) {
grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr;
grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
+ grpc_chttp2_stream_global *stream_global;
GPR_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0);
@@ -638,6 +642,11 @@
grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
+ while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global, &stream_global)) {
+ fail_pending_writes(exec_ctx, stream_global);
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
+ }
+
/* leave the writing flag up on shutdown to prevent further writes in unlock()
from starting */
t->writing_active = 0;
@@ -1040,6 +1049,12 @@
t->parsing.incoming_stream = NULL;
grpc_chttp2_parsing_become_skip_parser(exec_ctx, &t->parsing);
}
+ if (s->parsing.data_parser.parsing_frame != NULL) {
+ grpc_chttp2_incoming_byte_stream_finished(
+ exec_ctx, s->parsing.data_parser.parsing_frame, 0, 0);
+ s->parsing.data_parser.parsing_frame = NULL;
+ }
+
if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
close_transport_locked(exec_ctx, t);
}
@@ -1107,6 +1122,16 @@
}
}
+static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
+ grpc_chttp2_stream_global *stream_global) {
+ grpc_chttp2_complete_closure_step(
+ exec_ctx, &stream_global->send_initial_metadata_finished, 0);
+ grpc_chttp2_complete_closure_step(
+ exec_ctx, &stream_global->send_trailing_metadata_finished, 0);
+ grpc_chttp2_complete_closure_step(exec_ctx,
+ &stream_global->send_message_finished, 0);
+}
+
void grpc_chttp2_mark_stream_closed(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, int close_reads,
@@ -1123,6 +1148,13 @@
}
if (close_writes && !stream_global->write_closed) {
stream_global->write_closed = 1;
+ if (TRANSPORT_FROM_GLOBAL(transport_global)->writing_active) {
+ GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes");
+ grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
+ stream_global);
+ } else {
+ fail_pending_writes(exec_ctx, stream_global);
+ }
}
if (stream_global->read_closed && stream_global->write_closed) {
if (stream_global->id != 0 &&
@@ -1134,7 +1166,6 @@
remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global),
stream_global->id);
}
- stream_global->finished_close = 1;
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
}
}
@@ -1348,7 +1379,6 @@
GPR_ASSERT(stream_global->write_closed);
GPR_ASSERT(stream_global->read_closed);
remove_stream(exec_ctx, t, stream_global->id);
- stream_global->finished_close = 1;
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
}
}
@@ -1479,6 +1509,10 @@
*slice = gpr_slice_buffer_take_first(&bs->slices);
unlock(exec_ctx, bs->transport);
return 1;
+ } else if (bs->failed) {
+ grpc_exec_ctx_enqueue(exec_ctx, on_complete, 0);
+ unlock(exec_ctx, bs->transport);
+ return 0;
} else {
bs->on_next = on_complete;
bs->next = slice;
@@ -1513,7 +1547,29 @@
}
void grpc_chttp2_incoming_byte_stream_finished(
- grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs) {
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
+ int from_parsing_thread) {
+ if (!success) {
+ if (from_parsing_thread) {
+ gpr_mu_lock(&bs->transport->mu);
+ }
+ grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, 0);
+ bs->on_next = NULL;
+ bs->failed = 1;
+ if (from_parsing_thread) {
+ gpr_mu_unlock(&bs->transport->mu);
+ }
+ } else {
+#ifndef NDEBUG
+ if (from_parsing_thread) {
+ gpr_mu_lock(&bs->transport->mu);
+ }
+ GPR_ASSERT(bs->on_next == NULL);
+ if (from_parsing_thread) {
+ gpr_mu_unlock(&bs->transport->mu);
+ }
+#endif
+ }
incoming_byte_stream_unref(bs);
}
@@ -1534,6 +1590,7 @@
gpr_slice_buffer_init(&incoming_byte_stream->slices);
incoming_byte_stream->on_next = NULL;
incoming_byte_stream->is_tail = 1;
+ incoming_byte_stream->failed = 0;
if (add_to_queue->head == NULL) {
add_to_queue->head = incoming_byte_stream;
} else {
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
index a171855..475c792 100644
--- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
+++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
@@ -91,6 +91,7 @@
<Compile Include="ContextPropagationTest.cs" />
<Compile Include="MetadataTest.cs" />
<Compile Include="PerformanceTest.cs" />
+ <Compile Include="SanityTest.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
diff --git a/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
index 48b5d78..74f7f24 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
@@ -167,18 +167,18 @@
() => Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified)));
}
- // Test attribute commented out to prevent running as part of the default test suite.
- // [Test]
- // [Category("Performance")]
+ [Test]
+ [Category("Performance")]
+ [Ignore("Prevent running on Jenkins")]
public void NowBenchmark()
{
// approx Timespec.Now latency <33ns
BenchmarkUtil.RunBenchmark(10000000, 1000000000, () => { var now = Timespec.Now; });
}
-
- // Test attribute commented out to prevent running as part of the default test suite.
- // [Test]
- // [Category("Performance")]
+
+ [Test]
+ [Category("Performance")]
+ [Ignore("Prevent running on Jenkins")]
public void PreciseNowBenchmark()
{
// approx Timespec.PreciseNow latency <18ns (when compiled with GRPC_TIMERS_RDTSC)
diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
index 073c502..af55cb0 100644
--- a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
+++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
@@ -59,6 +59,8 @@
[Test]
public void CompletionQueueCreateDestroyBenchmark()
{
+ GrpcEnvironment.AddRef(); // completion queue requires gRPC environment being initialized.
+
BenchmarkUtil.RunBenchmark(
10, 10,
() =>
@@ -66,6 +68,8 @@
CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create();
cq.Dispose();
});
+
+ GrpcEnvironment.Release();
}
/// <summary>
diff --git a/src/csharp/Grpc.Core.Tests/PerformanceTest.cs b/src/csharp/Grpc.Core.Tests/PerformanceTest.cs
index 5516cd3..6815839 100644
--- a/src/csharp/Grpc.Core.Tests/PerformanceTest.cs
+++ b/src/csharp/Grpc.Core.Tests/PerformanceTest.cs
@@ -67,10 +67,10 @@
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
-
- // Test attribute commented out to prevent running as part of the default test suite.
- //[Test]
- //[Category("Performance")]
+
+ [Test]
+ [Category("Performance")]
+ [Ignore("Prevent running on Jenkins")]
public void UnaryCallPerformance()
{
var profiler = new BasicProfiler();
diff --git a/src/csharp/Grpc.Core.Tests/SanityTest.cs b/src/csharp/Grpc.Core.Tests/SanityTest.cs
new file mode 100644
index 0000000..343ab1e
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/SanityTest.cs
@@ -0,0 +1,125 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using Grpc.Core;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+
+namespace Grpc.Core.Tests
+{
+ public class SanityTest
+ {
+ /// <summary>
+ /// Because we depend on a native library, sometimes when things go wrong, the
+ /// entire NUnit test process crashes. To be able to track down problems better,
+ /// the NUnit tests are run by run_tests.py script in a separate process per test class.
+ /// The list of tests to run is stored in src/csharp/tests.json.
+ /// This test checks that the tests.json file is up to date by discovering all the
+ /// existing NUnit tests in all test assemblies and comparing to contents of tests.json.
+ /// </summary>
+ [Test]
+ public void TestsJsonUpToDate()
+ {
+ var testClasses = DiscoverAllTestClasses();
+ string testsJson = GetTestsJson();
+
+ // we don't have a JSON parser at hand, but check that the test class
+ // name is contained in the file instead.
+ foreach (var className in testClasses) {
+ Assert.IsTrue(testsJson.Contains(className),
+ string.Format("Test class \"{0}\" is missing in C# tests.json file", className));
+ }
+ }
+
+ /// <summary>
+ /// Gets list of all test classes obtained by inspecting all the test assemblies.
+ /// </summary>
+ private List<string> DiscoverAllTestClasses()
+ {
+ var assemblies = GetTestAssemblies();
+
+ var testClasses = new List<string>();
+ foreach (var assembly in assemblies)
+ {
+ foreach (var t in assembly.GetTypes())
+ {
+ foreach (var m in t.GetMethods())
+ {
+ var attributes = m.GetCustomAttributes(typeof(NUnit.Framework.TestAttribute), true);
+ if (attributes.Length > 0)
+ {
+ testClasses.Add(t.FullName);
+ break;
+ }
+
+ }
+ }
+ }
+ testClasses.Sort();
+ return testClasses;
+ }
+
+ private string GetTestsJson()
+ {
+ var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ var testsJsonFile = Path.Combine(assemblyDir, "..", "..", "..", "tests.json");
+
+ return File.ReadAllText(testsJsonFile);
+ }
+
+ private List<Assembly> GetTestAssemblies()
+ {
+ var result = new List<Assembly>();
+ var executingAssembly = Assembly.GetExecutingAssembly();
+
+ result.Add(executingAssembly);
+
+ var otherAssemblies = new[] {
+ "Grpc.Examples.Tests",
+ "Grpc.HealthCheck.Tests",
+ "Grpc.IntegrationTesting"
+ };
+ foreach (var assemblyName in otherAssemblies)
+ {
+ var location = executingAssembly.Location.Replace("Grpc.Core.Tests", assemblyName);
+ result.Add(Assembly.LoadFrom(location));
+ }
+ return result;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core.Tests/ShutdownTest.cs b/src/csharp/Grpc.Core.Tests/ShutdownTest.cs
index a2be7dd..10d666d 100644
--- a/src/csharp/Grpc.Core.Tests/ShutdownTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ShutdownTest.cs
@@ -61,17 +61,20 @@
}
[Test]
- public async Task AbandonedCall()
+ public async Task AbandonedCall_ServerKillAsync()
{
+ var readyToShutdown = new TaskCompletionSource<object>();
helper.DuplexStreamingHandler = new DuplexStreamingServerMethod<string, string>(async (requestStream, responseStream, context) =>
{
+ readyToShutdown.SetResult(null);
await requestStream.ToListAsync();
});
- var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall(new CallOptions(deadline: DateTime.UtcNow.AddMilliseconds(1))));
+ var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall());
+ await readyToShutdown.Task; // make sure handler is running
- channel.ShutdownAsync().Wait();
- server.ShutdownAsync().Wait();
+ await channel.ShutdownAsync(); // channel.ShutdownAsync() works even if there's a pending call.
+ await server.KillAsync(); // server.ShutdownAsync() would hang waiting for the call to finish.
}
}
}
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 0fadabe..d120f95 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -171,6 +171,8 @@
handle.CancelAllCalls();
await shutdownTcs.Task.ConfigureAwait(false);
DisposeHandle();
+
+ await Task.Run(() => GrpcEnvironment.Release()).ConfigureAwait(false);
}
internal void AddCallReference(object call)
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index c48ac71..b0d920a 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -41,6 +41,9 @@
<Reference Include="CommandLine">
<HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
</Reference>
+ <Reference Include="Moq">
+ <HintPath>..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath>
+ </Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
</Reference>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
index 5facb87..18168f9 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
@@ -140,12 +140,14 @@
}
[Test]
+ [Ignore("TODO: see #4427")]
public async Task StatusCodeAndMessage()
{
await InteropClient.RunStatusCodeAndMessageAsync(client);
}
[Test]
+ [Ignore("TODO: see #4427")]
public void UnimplementedMethod()
{
InteropClient.RunUnimplementedMethod(UnimplementedService.NewClient(channel));
diff --git a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
index 35230f4..1c8bfed 100644
--- a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
@@ -40,6 +40,7 @@
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
+using Moq;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
@@ -50,37 +51,37 @@
Server server;
Channel channel;
TestService.ITestServiceClient client;
+ List<ChannelOption> options;
+ Mock<TestService.ITestService> serviceMock;
+ AsyncAuthInterceptor asyncAuthInterceptor;
- [TestFixtureSetUp]
+ [SetUp]
public void Init()
{
- var serverCredentials = new SslServerCredentials(new[] { new KeyCertificatePair(File.ReadAllText(TestCredentials.ServerCertChainPath), File.ReadAllText(TestCredentials.ServerPrivateKeyPath)) });
+ serviceMock = new Mock<TestService.ITestService>();
+ serviceMock.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<ServerCallContext>()))
+ .Returns(new Func<SimpleRequest, ServerCallContext, Task<SimpleResponse>>(UnaryCallHandler));
+
server = new Server
{
- Services = { TestService.BindService(new TestServiceImpl()) },
- Ports = { { Host, ServerPort.PickUnused, serverCredentials } }
+ Services = { TestService.BindService(serviceMock.Object) },
+ Ports = { { Host, ServerPort.PickUnused, TestCredentials.CreateSslServerCredentials() } }
};
server.Start();
- var options = new List<ChannelOption>
+ options = new List<ChannelOption>
{
new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride)
};
- var asyncAuthInterceptor = new AsyncAuthInterceptor(async (context, metadata) =>
+ asyncAuthInterceptor = new AsyncAuthInterceptor(async (context, metadata) =>
{
- await Task.Delay(100); // make sure the operation is asynchronous.
+ await Task.Delay(100).ConfigureAwait(false); // make sure the operation is asynchronous.
metadata.Add("authorization", "SECRET_TOKEN");
});
-
- var clientCredentials = ChannelCredentials.Create(
- new SslCredentials(File.ReadAllText(TestCredentials.ClientCertAuthorityPath)),
- CallCredentials.FromInterceptor(asyncAuthInterceptor));
- channel = new Channel(Host, server.Ports.Single().BoundPort, clientCredentials, options);
- client = TestService.NewClient(channel);
}
- [TestFixtureTearDown]
+ [TearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
@@ -90,8 +91,29 @@
[Test]
public void MetadataCredentials()
{
- var response = client.UnaryCall(new SimpleRequest { ResponseSize = 10 });
- Assert.AreEqual(10, response.Payload.Body.Length);
+ var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(),
+ CallCredentials.FromInterceptor(asyncAuthInterceptor));
+ channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options);
+ client = TestService.NewClient(channel);
+
+ client.UnaryCall(new SimpleRequest {});
+ }
+
+ [Test]
+ public void MetadataCredentials_PerCall()
+ {
+ channel = new Channel(Host, server.Ports.Single().BoundPort, TestCredentials.CreateSslCredentials(), options);
+ client = TestService.NewClient(channel);
+
+ var callCredentials = CallCredentials.FromInterceptor(asyncAuthInterceptor);
+ client.UnaryCall(new SimpleRequest { }, new CallOptions(credentials: callCredentials));
+ }
+
+ private Task<SimpleResponse> UnaryCallHandler(SimpleRequest request, ServerCallContext context)
+ {
+ var authToken = context.RequestHeaders.First((entry) => entry.Key == "authorization").Value;
+ Assert.AreEqual("SECRET_TOKEN", authToken);
+ return Task.FromResult(new SimpleResponse());
}
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
index 2b51526..3dd91b7 100644
--- a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
@@ -75,9 +75,10 @@
serverRunner.StopAsync().Wait();
}
- // Test attribute commented out to prevent running as part of the default test suite.
- //[Test]
- //[Category("Performance")]
+
+ [Test]
+ [Category("Performance")]
+ [Ignore("Prevent running on Jenkins")]
public async Task ClientServerRunner()
{
var config = new ClientConfig
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index bdb3dad..5c59af1 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -11,6 +11,7 @@
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
+ <package id="Moq" version="4.2.1510.2205" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" />
</packages>
\ No newline at end of file
diff --git a/src/csharp/tests.json b/src/csharp/tests.json
new file mode 100644
index 0000000..4aa9366
--- /dev/null
+++ b/src/csharp/tests.json
@@ -0,0 +1,45 @@
+{
+ "assemblies": [
+ "Grpc.Core.Tests",
+ "Grpc.Examples.Tests",
+ "Grpc.HealthCheck.Tests",
+ "Grpc.IntegrationTesting"
+ ],
+ "tests": [
+ "Grpc.Core.Internal.Tests.AsyncCallTest",
+ "Grpc.Core.Internal.Tests.ChannelArgsSafeHandleTest",
+ "Grpc.Core.Internal.Tests.CompletionQueueEventTest",
+ "Grpc.Core.Internal.Tests.CompletionQueueSafeHandleTest",
+ "Grpc.Core.Internal.Tests.MetadataArraySafeHandleTest",
+ "Grpc.Core.Internal.Tests.TimespecTest",
+ "Grpc.Core.Tests.CallCredentialsTest",
+ "Grpc.Core.Tests.CallOptionsTest",
+ "Grpc.Core.Tests.ChannelCredentialsTest",
+ "Grpc.Core.Tests.ChannelOptionsTest",
+ "Grpc.Core.Tests.ChannelTest",
+ "Grpc.Core.Tests.ClientServerTest",
+ "Grpc.Core.Tests.CompressionTest",
+ "Grpc.Core.Tests.ContextPropagationTest",
+ "Grpc.Core.Tests.GrpcEnvironmentTest",
+ "Grpc.Core.Tests.MarshallingErrorsTest",
+ "Grpc.Core.Tests.MetadataTest",
+ "Grpc.Core.Tests.NUnitVersionTest",
+ "Grpc.Core.Tests.PerformanceTest",
+ "Grpc.Core.Tests.PInvokeTest",
+ "Grpc.Core.Tests.ResponseHeadersTest",
+ "Grpc.Core.Tests.SanityTest",
+ "Grpc.Core.Tests.ServerTest",
+ "Grpc.Core.Tests.ShutdownTest",
+ "Grpc.Core.Tests.TimeoutsTest",
+ "Grpc.Core.Tests.UserAgentStringTest",
+ "Math.Tests.MathClientServerTest",
+ "Grpc.HealthCheck.Tests.HealthClientServerTest",
+ "Grpc.HealthCheck.Tests.HealthServiceImplTest",
+ "Grpc.IntegrationTesting.HeaderInterceptorTest",
+ "Grpc.IntegrationTesting.HistogramTest",
+ "Grpc.IntegrationTesting.InteropClientServerTest",
+ "Grpc.IntegrationTesting.MetadataCredentialsTest",
+ "Grpc.IntegrationTesting.RunnerClientServerTest",
+ "Grpc.IntegrationTesting.SslCredentialsTest"
+ ]
+}
\ No newline at end of file
diff --git a/src/node/interop/async_delay_queue.js b/src/node/interop/async_delay_queue.js
new file mode 100644
index 0000000..2bd3ca4
--- /dev/null
+++ b/src/node/interop/async_delay_queue.js
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+'use strict';
+
+var _ = require('lodash');
+
+/**
+ * This class represents a queue of callbacks that must happen sequentially, each
+ * with a specific delay after the previous event.
+ */
+function AsyncDelayQueue() {
+ this.queue = [];
+
+ this.callback_pending = false;
+}
+
+/**
+ * Run the next callback after its corresponding delay, if there are any
+ * remaining.
+ */
+AsyncDelayQueue.prototype.runNext = function() {
+ var next = this.queue.shift();
+ var continueCallback = _.bind(this.runNext, this);
+ if (next) {
+ this.callback_pending = true;
+ setTimeout(function() {
+ next.callback(continueCallback);
+ }, next.delay);
+ } else {
+ this.callback_pending = false;
+ }
+};
+
+/**
+ * Add a callback to be called with a specific delay after now or after the
+ * current last item in the queue or current pending callback, whichever is
+ * latest.
+ * @param {function(function())} callback The callback
+ * @param {Number} The delay to apply, in milliseconds
+ */
+AsyncDelayQueue.prototype.add = function(callback, delay) {
+ this.queue.push({callback: callback, delay: delay});
+ if (!this.callback_pending) {
+ this.runNext();
+ }
+};
+
+module.exports = AsyncDelayQueue;
diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js
index 5321005..9526b5d 100644
--- a/src/node/interop/interop_server.js
+++ b/src/node/interop/interop_server.js
@@ -36,6 +36,7 @@
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
+var AsyncDelayQueue = require('./async_delay_queue');
var grpc = require('..');
var testProto = grpc.load({
root: __dirname + '/../../..',
@@ -155,6 +156,7 @@
*/
function handleStreamingOutput(call) {
echoHeader(call);
+ var delay_queue = new AsyncDelayQueue();
var req = call.request;
if (req.response_status) {
var status = req.response_status;
@@ -163,9 +165,15 @@
return;
}
_.each(req.response_parameters, function(resp_param) {
- call.write({payload: getPayload(req.response_type, resp_param.size)});
+ delay_queue.add(function(next) {
+ call.write({payload: getPayload(req.response_type, resp_param.size)});
+ next();
+ }, resp_param.interval_us);
});
- call.end(getEchoTrailer(call));
+ delay_queue.add(function(next) {
+ call.end(getEchoTrailer(call));
+ next();
+ });
}
/**
@@ -175,6 +183,7 @@
*/
function handleFullDuplex(call) {
echoHeader(call);
+ var delay_queue = new AsyncDelayQueue();
call.on('data', function(value) {
if (value.response_status) {
var status = value.response_status;
@@ -183,11 +192,17 @@
return;
}
_.each(value.response_parameters, function(resp_param) {
- call.write({payload: getPayload(value.response_type, resp_param.size)});
+ delay_queue.add(function(next) {
+ call.write({payload: getPayload(value.response_type, resp_param.size)});
+ next();
+ }, resp_param.interval_us);
});
});
call.on('end', function() {
- call.end(getEchoTrailer(call));
+ delay_queue.add(function(next) {
+ call.end(getEchoTrailer(call));
+ next();
+ });
});
}
diff --git a/src/php/ext/grpc/package.xml b/src/php/ext/grpc/package.xml
index a2e3e28..79a0a79 100644
--- a/src/php/ext/grpc/package.xml
+++ b/src/php/ext/grpc/package.xml
@@ -10,11 +10,11 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
- <date>2015-10-21</date>
- <time>17:04:32</time>
+ <date>2015-12-15</date>
+ <time>13:49:29</time>
<version>
- <release>0.6.1</release>
- <api>0.6.0</api>
+ <release>0.7.0</release>
+ <api>0.7.0</api>
</version>
<stability>
<release>beta</release>
@@ -22,19 +22,21 @@
</stability>
<license>BSD</license>
<notes>
-- fixed undefined constant fatal error when run with apache/nginx #2275
+- Breaking change to Credentials class (removed) #3765
+- Replaced by ChannelCredentials and CallCredentials class #3765
+- New plugin based metadata auth API #4394
</notes>
<contents>
<dir baseinstalldir="/" name="/">
<file baseinstalldir="/" md5sum="6f19828fb869b7b8a590cbb76b4f996d" name="byte_buffer.c" role="src" />
<file baseinstalldir="/" md5sum="c8de0f819499c48adfc8d7f472c0196b" name="byte_buffer.h" role="src" />
- <file baseinstalldir="/" md5sum="d64c9005993de02abac55664b0b9e0b2" name="call.c" role="src" />
- <file baseinstalldir="/" md5sum="26acbf04c30162c2d2aca4688bb2aec8" name="call.h" role="src" />
- <file baseinstalldir="/" md5sum="6fa13d260dfde216f795225644f04e7a" name="call_credentials.c" role="src" />
- <file baseinstalldir="/" md5sum="e45269975f9a30fd349a90daf6b31aa2" name="call_credentials.h" role="src" />
- <file baseinstalldir="/" md5sum="0779db3b196c98081b2260ceec22cd4d" name="channel.c" role="src" />
+ <file baseinstalldir="/" md5sum="ee7eb7757f9e6f0e36f8f616b6bd0af5" name="call.c" role="src" />
+ <file baseinstalldir="/" md5sum="44c56bd9912d2538cbd6059e3e0452b6" name="call.h" role="src" />
+ <file baseinstalldir="/" md5sum="ff90f6c03ed44b5f4170bf3259a6704e" name="call_credentials.c" role="src" />
+ <file baseinstalldir="/" md5sum="3c3860e1d84f43cb6b2fbaa8d2ae1ab7" name="call_credentials.h" role="src" />
+ <file baseinstalldir="/" md5sum="00b44de389fbafa68afe8173045940af" name="channel.c" role="src" />
<file baseinstalldir="/" md5sum="ed4b00c0cf3702b115d0cfa87450dc09" name="channel.h" role="src" />
- <file baseinstalldir="/" md5sum="1b40f50fa6184ad7d24a961ac76151ff" name="channel_credentials.c" role="src" />
+ <file baseinstalldir="/" md5sum="d6e32503492b22bca1baf119d6c5e373" name="channel_credentials.c" role="src" />
<file baseinstalldir="/" md5sum="a86250e03f610ce6c2c7595a84e08821" name="channel_credentials.h" role="src" />
<file baseinstalldir="/" md5sum="55ab7a42f9dd9bfc7e28a61cfc5fca63" name="completion_queue.c" role="src" />
<file baseinstalldir="/" md5sum="f10b5bb232d74a6878e829e2e76cdaa2" name="completion_queue.h" role="src" />
@@ -130,5 +132,22 @@
- fixed undefined constant fatal error when run with apache/nginx #2275
</notes>
</release>
+ <release>
+ <version>
+ <release>0.7.0</release>
+ <api>0.7.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <date>2015-12-15</date>
+ <license>BSD</license>
+ <notes>
+- Breaking change to Credentials class (removed) #3765
+- Replaced by ChannelCredentials and CallCredentials class #3765
+- New plugin based metadata auth API #4394
+ </notes>
+ </release>
</changelog>
</package>
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index e1a4b8e..5aceac6 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -49,13 +49,14 @@
grpc_server *server;
grpc_completion_queue *cq;
grpc_bad_client_server_side_validator validator;
+ void *registered_method;
gpr_event done_thd;
gpr_event done_write;
} thd_args;
static void thd_func(void *arg) {
thd_args *a = arg;
- a->validator(a->server, a->cq);
+ a->validator(a->server, a->cq, a->registered_method);
gpr_event_set(&a->done_thd, (void *)1);
}
@@ -110,6 +111,9 @@
gpr_event_init(&a.done_write);
a.validator = validator;
grpc_server_register_completion_queue(a.server, a.cq, NULL);
+ a.registered_method =
+ grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD,
+ GRPC_BAD_CLIENT_REGISTERED_HOST);
grpc_server_start(a.server);
transport = grpc_create_chttp2_transport(&exec_ctx, NULL, sfd.server, 0);
server_setup_transport(&a, transport);
diff --git a/test/core/bad_client/bad_client.h b/test/core/bad_client/bad_client.h
index 01beda6..2dd100a 100644
--- a/test/core/bad_client/bad_client.h
+++ b/test/core/bad_client/bad_client.h
@@ -37,8 +37,12 @@
#include <grpc/grpc.h>
#include "test/core/util/test_config.h"
-typedef void (*grpc_bad_client_server_side_validator)(
- grpc_server *server, grpc_completion_queue *cq);
+#define GRPC_BAD_CLIENT_REGISTERED_METHOD "/registered/bar"
+#define GRPC_BAD_CLIENT_REGISTERED_HOST "localhost"
+
+typedef void (*grpc_bad_client_server_side_validator)(grpc_server *server,
+ grpc_completion_queue *cq,
+ void *registered_method);
#define GRPC_BAD_CLIENT_DISCONNECT 1
diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py
index 386a896..45fcb69 100755
--- a/test/core/bad_client/gen_build_yaml.py
+++ b/test/core/bad_client/gen_build_yaml.py
@@ -44,6 +44,7 @@
'connection_prefix': default_test_options,
'headers': default_test_options,
'initial_settings_frame': default_test_options,
+ 'server_registered_method': default_test_options,
'simple_request': default_test_options,
'unknown_frame': default_test_options,
}
diff --git a/test/core/bad_client/tests/badreq.c b/test/core/bad_client/tests/badreq.c
index f0d7dac..6d59d25 100644
--- a/test/core/bad_client/tests/badreq.c
+++ b/test/core/bad_client/tests/badreq.c
@@ -42,7 +42,8 @@
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
"\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */
-static void verifier(grpc_server *server, grpc_completion_queue *cq) {
+static void verifier(grpc_server *server, grpc_completion_queue *cq,
+ void *registered_method) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(cq,
GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
diff --git a/test/core/bad_client/tests/connection_prefix.c b/test/core/bad_client/tests/connection_prefix.c
index 90d37a3..66ff8c2 100644
--- a/test/core/bad_client/tests/connection_prefix.c
+++ b/test/core/bad_client/tests/connection_prefix.c
@@ -34,7 +34,8 @@
#include "test/core/bad_client/bad_client.h"
#include "src/core/surface/server.h"
-static void verifier(grpc_server *server, grpc_completion_queue *cq) {
+static void verifier(grpc_server *server, grpc_completion_queue *cq,
+ void *registered_method) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(cq,
GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
diff --git a/test/core/bad_client/tests/headers.c b/test/core/bad_client/tests/headers.c
index c404fd2..2186a4f 100644
--- a/test/core/bad_client/tests/headers.c
+++ b/test/core/bad_client/tests/headers.c
@@ -38,7 +38,8 @@
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
"\x00\x00\x00\x04\x00\x00\x00\x00\x00"
-static void verifier(grpc_server *server, grpc_completion_queue *cq) {
+static void verifier(grpc_server *server, grpc_completion_queue *cq,
+ void *registered_method) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(cq,
GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
diff --git a/test/core/bad_client/tests/initial_settings_frame.c b/test/core/bad_client/tests/initial_settings_frame.c
index cd8771e..fb6149c 100644
--- a/test/core/bad_client/tests/initial_settings_frame.c
+++ b/test/core/bad_client/tests/initial_settings_frame.c
@@ -37,7 +37,8 @@
#define PFX_STR "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
#define ONE_SETTING_HDR "\x00\x00\x06\x04\x00\x00\x00\x00\x00"
-static void verifier(grpc_server *server, grpc_completion_queue *cq) {
+static void verifier(grpc_server *server, grpc_completion_queue *cq,
+ void *registered_method) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(cq,
GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
diff --git a/test/core/bad_client/tests/server_registered_method.c b/test/core/bad_client/tests/server_registered_method.c
new file mode 100644
index 0000000..d2876ff
--- /dev/null
+++ b/test/core/bad_client/tests/server_registered_method.c
@@ -0,0 +1,155 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "test/core/bad_client/bad_client.h"
+
+#include <string.h>
+
+#include "test/core/end2end/cq_verifier.h"
+#include "src/core/surface/server.h"
+
+#define PFX_STR \
+ "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
+ "\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */ \
+ "\x00\x00\xd0\x01\x04\x00\x00\x00\x01" \
+ "\x10\x05:path\x0f/registered/bar" \
+ "\x10\x07:scheme\x04http" \
+ "\x10\x07:method\x04POST" \
+ "\x10\x0a:authority\x09localhost" \
+ "\x10\x0c" \
+ "content-type\x10" \
+ "application/grpc" \
+ "\x10\x14grpc-accept-encoding\x15identity,deflate,gzip" \
+ "\x10\x02te\x08trailers" \
+ "\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
+
+static void *tag(gpr_intptr t) { return (void *)t; }
+
+static void verifier_succeeds(grpc_server *server, grpc_completion_queue *cq,
+ void *registered_method) {
+ grpc_call_error error;
+ grpc_call *s;
+ cq_verifier *cqv = cq_verifier_create(cq);
+ grpc_metadata_array request_metadata_recv;
+ gpr_timespec deadline;
+ grpc_byte_buffer *payload = NULL;
+
+ grpc_metadata_array_init(&request_metadata_recv);
+
+ error = grpc_server_request_registered_call(server, registered_method, &s,
+ &deadline, &request_metadata_recv,
+ &payload, cq, cq, tag(101));
+ GPR_ASSERT(GRPC_CALL_OK == error);
+ cq_expect_completion(cqv, tag(101), 1);
+ cq_verify(cqv);
+
+ GPR_ASSERT(payload != NULL);
+
+ grpc_metadata_array_destroy(&request_metadata_recv);
+ grpc_call_destroy(s);
+ grpc_byte_buffer_destroy(payload);
+ cq_verifier_destroy(cqv);
+}
+
+static void verifier_fails(grpc_server *server, grpc_completion_queue *cq,
+ void *registered_method) {
+ grpc_call_error error;
+ grpc_call *s;
+ cq_verifier *cqv = cq_verifier_create(cq);
+ grpc_metadata_array request_metadata_recv;
+ gpr_timespec deadline;
+ grpc_byte_buffer *payload = NULL;
+
+ grpc_metadata_array_init(&request_metadata_recv);
+
+ error = grpc_server_request_registered_call(server, registered_method, &s,
+ &deadline, &request_metadata_recv,
+ &payload, cq, cq, tag(101));
+ GPR_ASSERT(GRPC_CALL_OK == error);
+ cq_expect_completion(cqv, tag(101), 1);
+ cq_verify(cqv);
+
+ GPR_ASSERT(payload == NULL);
+
+ grpc_metadata_array_destroy(&request_metadata_recv);
+ grpc_call_destroy(s);
+ cq_verifier_destroy(cqv);
+}
+
+int main(int argc, char **argv) {
+ grpc_test_init(argc, argv);
+
+ /* body generated with
+ * tools/codegen/core/gen_server_registered_method_bad_client_test_body.py */
+ GRPC_RUN_BAD_CLIENT_TEST(verifier_fails,
+ PFX_STR "\x00\x00\x00\x00\x00\x00\x00\x00\x01",
+ GRPC_BAD_CLIENT_DISCONNECT);
+ GRPC_RUN_BAD_CLIENT_TEST(verifier_fails,
+ PFX_STR "\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00",
+ GRPC_BAD_CLIENT_DISCONNECT);
+ GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, PFX_STR
+ "\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x00",
+ GRPC_BAD_CLIENT_DISCONNECT);
+ GRPC_RUN_BAD_CLIENT_TEST(verifier_fails, PFX_STR
+ "\x00\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00",
+ GRPC_BAD_CLIENT_DISCONNECT);
+ GRPC_RUN_BAD_CLIENT_TEST(
+ verifier_fails,
+ PFX_STR "\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00",
+ GRPC_BAD_CLIENT_DISCONNECT);
+ GRPC_RUN_BAD_CLIENT_TEST(
+ verifier_succeeds,
+ PFX_STR "\x00\x00\x05\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00", 0);
+ GRPC_RUN_BAD_CLIENT_TEST(
+ verifier_fails,
+ PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x01",
+ GRPC_BAD_CLIENT_DISCONNECT);
+ GRPC_RUN_BAD_CLIENT_TEST(
+ verifier_succeeds,
+ PFX_STR "\x00\x00\x06\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00",
+ 0);
+ GRPC_RUN_BAD_CLIENT_TEST(
+ verifier_fails,
+ PFX_STR "\x00\x00\x05\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02",
+ GRPC_BAD_CLIENT_DISCONNECT);
+ GRPC_RUN_BAD_CLIENT_TEST(
+ verifier_fails,
+ PFX_STR "\x00\x00\x06\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00",
+ GRPC_BAD_CLIENT_DISCONNECT);
+ GRPC_RUN_BAD_CLIENT_TEST(
+ verifier_succeeds, PFX_STR
+ "\x00\x00\x07\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x02\x00\x00",
+ 0);
+
+ return 0;
+}
diff --git a/test/core/bad_client/tests/server_registered_method.headers b/test/core/bad_client/tests/server_registered_method.headers
new file mode 100644
index 0000000..06ee73c
--- /dev/null
+++ b/test/core/bad_client/tests/server_registered_method.headers
@@ -0,0 +1,12 @@
+# headers used in simple_request.c
+# use tools/codegen/core/gen_header_frame.py to generate the binary strings
+# contained in the source code
+:path: /registered/bar
+:scheme: http
+:method: POST
+:authority: localhost
+content-type: application/grpc
+grpc-accept-encoding: identity,deflate,gzip
+te: trailers
+user-agent: bad-client grpc-c/0.12.0.0 (linux)
+
diff --git a/test/core/bad_client/tests/simple_request.c b/test/core/bad_client/tests/simple_request.c
index 125a9fa..4df586e 100644
--- a/test/core/bad_client/tests/simple_request.c
+++ b/test/core/bad_client/tests/simple_request.c
@@ -79,7 +79,8 @@
static void *tag(gpr_intptr t) { return (void *)t; }
-static void verifier(grpc_server *server, grpc_completion_queue *cq) {
+static void verifier(grpc_server *server, grpc_completion_queue *cq,
+ void *registered_method) {
grpc_call_error error;
grpc_call *s;
grpc_call_details call_details;
@@ -104,7 +105,8 @@
cq_verifier_destroy(cqv);
}
-static void failure_verifier(grpc_server *server, grpc_completion_queue *cq) {
+static void failure_verifier(grpc_server *server, grpc_completion_queue *cq,
+ void *registered_method) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(cq,
GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
diff --git a/test/core/bad_client/tests/unknown_frame.c b/test/core/bad_client/tests/unknown_frame.c
index 3f8658b..2ef340e 100644
--- a/test/core/bad_client/tests/unknown_frame.c
+++ b/test/core/bad_client/tests/unknown_frame.c
@@ -38,7 +38,8 @@
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" \
"\x00\x00\x00\x04\x00\x00\x00\x00\x00"
-static void verifier(grpc_server *server, grpc_completion_queue *cq) {
+static void verifier(grpc_server *server, grpc_completion_queue *cq,
+ void *registered_method) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(cq,
GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20),
diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c
index 5cf6bfe..8a24d82 100644
--- a/test/core/surface/completion_queue_test.c
+++ b/test/core/surface/completion_queue_test.c
@@ -89,7 +89,7 @@
cc = grpc_completion_queue_create(NULL);
- grpc_cq_begin_op(cc);
+ grpc_cq_begin_op(cc, tag);
grpc_cq_end_op(&exec_ctx, cc, tag, 1, do_nothing_end_completion, NULL,
&completion);
@@ -148,7 +148,7 @@
cc = grpc_completion_queue_create(NULL);
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
- grpc_cq_begin_op(cc);
+ grpc_cq_begin_op(cc, tags[i]);
grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL,
&completions[i]);
}
@@ -160,7 +160,7 @@
}
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
- grpc_cq_begin_op(cc);
+ grpc_cq_begin_op(cc, tags[i]);
grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL,
&completions[i]);
}
@@ -226,14 +226,14 @@
}
/* wait until all other threads are plucking */
- gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100));
+ gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(1000));
ev = grpc_completion_queue_pluck(cc, create_test_tag(),
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT);
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
- grpc_cq_begin_op(cc);
+ grpc_cq_begin_op(cc, tags[i]);
grpc_cq_end_op(&exec_ctx, cc, tags[i], 1, do_nothing_end_completion, NULL,
&completions[i]);
}
@@ -279,7 +279,7 @@
gpr_log(GPR_INFO, "producer %d phase 1", opt->id);
for (i = 0; i < TEST_THREAD_EVENTS; i++) {
- grpc_cq_begin_op(opt->cc);
+ grpc_cq_begin_op(opt->cc, (void *)(gpr_intptr)1);
}
gpr_log(GPR_INFO, "producer %d phase 1 done", opt->id);
diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c
index 84b376a..14bfc95 100644
--- a/test/core/util/test_config.c
+++ b/test/core/util/test_config.c
@@ -127,6 +127,8 @@
backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO);
}
+ /* try to get a core dump for SIGTERM */
+ if (signum == SIGTERM) signum = SIGQUIT;
raise(signum);
}
@@ -145,6 +147,8 @@
GPR_ASSERT(sigaction(SIGABRT, &sa, NULL) == 0);
GPR_ASSERT(sigaction(SIGBUS, &sa, NULL) == 0);
GPR_ASSERT(sigaction(SIGSEGV, &sa, NULL) == 0);
+ GPR_ASSERT(sigaction(SIGTERM, &sa, NULL) == 0);
+ GPR_ASSERT(sigaction(SIGQUIT, &sa, NULL) == 0);
}
#else
static void install_crash_handler() {}
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index 6340007..05ef0c8 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -80,6 +80,24 @@
GPR_ASSERT(false);
}
}
+
+void NoopChecks(const InteropClientContextInspector& inspector,
+ const SimpleRequest* request, const SimpleResponse* response) {}
+
+void CompressionChecks(const InteropClientContextInspector& inspector,
+ const SimpleRequest* request,
+ const SimpleResponse* response) {
+ GPR_ASSERT(request->response_compression() ==
+ GetInteropCompressionTypeFromCompressionAlgorithm(
+ inspector.GetCallCompressionAlgorithm()));
+ if (request->response_compression() == NONE) {
+ GPR_ASSERT(!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS));
+ } else if (request->response_type() == PayloadType::COMPRESSABLE) {
+ // requested compression and compressable response => results should always
+ // be compressed.
+ GPR_ASSERT(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS);
+ }
+}
} // namespace
InteropClient::ServiceStub::ServiceStub(std::shared_ptr<Channel> channel,
@@ -145,9 +163,14 @@
gpr_log(GPR_INFO, "Empty rpc done.");
}
-// Shared code to set large payload, make rpc and check response payload.
void InteropClient::PerformLargeUnary(SimpleRequest* request,
SimpleResponse* response) {
+ PerformLargeUnary(request, response, NoopChecks);
+}
+
+void InteropClient::PerformLargeUnary(SimpleRequest* request,
+ SimpleResponse* response,
+ CheckerFn custom_checks_fn) {
ClientContext context;
InteropClientContextInspector inspector(context);
// If the request doesn't already specify the response type, default to
@@ -157,21 +180,10 @@
request->mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
Status s = serviceStub_.Get()->UnaryCall(&context, *request, response);
-
- // Compression related checks.
- GPR_ASSERT(request->response_compression() ==
- GetInteropCompressionTypeFromCompressionAlgorithm(
- inspector.GetCallCompressionAlgorithm()));
- if (request->response_compression() == NONE) {
- GPR_ASSERT(!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS));
- } else if (request->response_type() == PayloadType::COMPRESSABLE) {
- // requested compression and compressable response => results should always
- // be compressed.
- GPR_ASSERT(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS);
- }
-
AssertOkOrPrintErrorStatus(s);
+ custom_checks_fn(inspector, request, response);
+
// Payload related checks.
if (request->response_type() != PayloadType::RANDOM) {
GPR_ASSERT(response->payload().type() == request->response_type());
@@ -293,7 +305,7 @@
SimpleResponse response;
request.set_response_type(payload_types[i]);
request.set_response_compression(compression_types[j]);
- PerformLargeUnary(&request, &response);
+ PerformLargeUnary(&request, &response, CompressionChecks);
gpr_log(GPR_INFO, "Large compressed unary done %s.", log_suffix);
gpr_free(log_suffix);
}
diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h
index 1bfb49d..97a6fd7 100644
--- a/test/cpp/interop/interop_client.h
+++ b/test/cpp/interop/interop_client.h
@@ -44,6 +44,11 @@
namespace grpc {
namespace testing {
+// Function pointer for custom checks.
+using CheckerFn =
+ std::function<void(const InteropClientContextInspector&,
+ const SimpleRequest*, const SimpleResponse*)>;
+
class InteropClient {
public:
explicit InteropClient(std::shared_ptr<Channel> channel);
@@ -100,6 +105,10 @@
};
void PerformLargeUnary(SimpleRequest* request, SimpleResponse* response);
+
+ /// Run \a custom_check_fn as an additional check.
+ void PerformLargeUnary(SimpleRequest* request, SimpleResponse* response,
+ CheckerFn custom_checks_fn);
void AssertOkOrPrintErrorStatus(const Status& s);
ServiceStub serviceStub_;
};
diff --git a/tools/codegen/core/gen_server_registered_method_bad_client_test_body.py b/tools/codegen/core/gen_server_registered_method_bad_client_test_body.py
new file mode 100755
index 0000000..76c9876
--- /dev/null
+++ b/tools/codegen/core/gen_server_registered_method_bad_client_test_body.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python2.7
+
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+def esc_c(line):
+ out = "\""
+ last_was_hex = False
+ for c in line:
+ if 32 <= c < 127:
+ if c in hex_bytes and last_was_hex:
+ out += "\"\""
+ if c != ord('"'):
+ out += chr(c)
+ else:
+ out += "\\\""
+ last_was_hex = False
+ else:
+ out += "\\x%02x" % c
+ last_was_hex = True
+ return out + "\""
+
+done = set()
+
+for message_length in range(0, 3):
+ for send_message_length in range(0, message_length + 1):
+ payload = [
+ 0,
+ (message_length >> 24) & 0xff,
+ (message_length >> 16) & 0xff,
+ (message_length >> 8) & 0xff,
+ (message_length) & 0xff
+ ] + send_message_length * [0]
+ for frame_length in range(0, len(payload) + 1):
+ is_end = frame_length == len(payload) and send_message_length == message_length
+ frame = [
+ (frame_length >> 16) & 0xff,
+ (frame_length >> 8) & 0xff,
+ (frame_length) & 0xff,
+ 0,
+ 1 if is_end else 0,
+ 0, 0, 0, 1
+ ] + payload[0:frame_length]
+ text = esc_c(frame)
+ if text not in done:
+ print 'GRPC_RUN_BAD_CLIENT_TEST(verifier_%s, PFX_STR %s, %s);' % (
+ 'succeeds' if is_end else 'fails',
+ text,
+ '0' if is_end else 'GRPC_BAD_CLIENT_DISCONNECT')
+ done.add(text)
diff --git a/tools/jenkins/grpc_interop_php/Dockerfile b/tools/jenkins/grpc_interop_php/Dockerfile
index 0780894..cf3e791 100644
--- a/tools/jenkins/grpc_interop_php/Dockerfile
+++ b/tools/jenkins/grpc_interop_php/Dockerfile
@@ -100,9 +100,10 @@
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
-# attempt to force a rebuild of the docker image after this point because
-# Protobuf-PHP codegen has been updated
-RUN echo 1
+# As an attempt to work around #4212, try to prefetch Protobuf-PHP dependency
+# into composer cache to prevent "composer install" from cloning on each build.
+RUN git clone --mirror https://github.com/stanley-cheung/Protobuf-PHP.git \
+ /root/.composer/cache/vcs/git-github.com-stanley-cheung-Protobuf-PHP.git/
# Download the patched PHP protobuf so that PHP gRPC clients can be generated
# from proto3 schemas.
@@ -113,10 +114,5 @@
&& rvm all do rake pear:package version=1.0 \
&& pear install Protobuf-1.0.tgz"
-# As an attempt to work around #4212, try to prefetch Protobuf-PHP dependency
-# into composer cache to prevent "composer install" from cloning on each build.
-RUN git clone --mirror https://github.com/stanley-cheung/Protobuf-PHP.git \
- /root/.composer/cache/vcs/git-github.com-stanley-cheung-Protobuf-PHP.git/
-
# Define the default command.
CMD ["bash"]
diff --git a/tools/jenkins/run_performance.sh b/tools/jenkins/run_performance.sh
index a60b1bb..d7e73d4 100755
--- a/tools/jenkins/run_performance.sh
+++ b/tools/jenkins/run_performance.sh
@@ -34,6 +34,10 @@
# Enter the gRPC repo root
cd $(dirname $0)/../..
+[[ $* =~ '--latency_profile' ]] \
+ && tools/profiling/latency_profile/run_latency_profile.sh \
+ || true
+
config=opt
make CONFIG=$config qps_worker qps_driver -j8
@@ -45,7 +49,7 @@
export QPS_WORKERS="localhost:10000,localhost:10010"
-bins/$config/qps_driver $*
+bins/$config/qps_driver
kill -2 $PID1 $PID2
wait
diff --git a/tools/profiling/latency_profile/run_latency_profile.sh b/tools/profiling/latency_profile/run_latency_profile.sh
index 41686be..64c3e58 100755
--- a/tools/profiling/latency_profile/run_latency_profile.sh
+++ b/tools/profiling/latency_profile/run_latency_profile.sh
@@ -11,6 +11,17 @@
mkdir -p reports
+# try to use pypy for generating reports
+# each trace dumps 7-8gig of text to disk, and processing this into a report is
+# heavyweight - so any speed boost is worthwhile
+# TODO(ctiller): consider rewriting report generation in C++ for performance
+if which pypy >/dev/null; then
+ PYTHON=pypy
+else
+ PYTHON=python2.7
+fi
+
+# start processes, interleaving report index generation
echo '<html><head></head><body>' > reports/index.html
for bin in $BINS
do
@@ -18,12 +29,27 @@
mv latency_trace.txt $bin.trace
echo "<a href='$bin.txt'>$bin</a><br/>" >> reports/index.html
done
+pids=""
+# generate report pages... this will take some time
+# run them in parallel: they take 1 cpu each
for bin in $BINS
do
- tools/profiling/latency_profile/profile_analyzer.py \
+ $PYTHON tools/profiling/latency_profile/profile_analyzer.py \
--source=$bin.trace --fmt=simple > reports/$bin.txt &
+ pids+=" $!"
done
echo '</body></html>' >> reports/index.html
-wait
+# make sure we kill the report generation if something goes wrong
+trap "kill $pids || true" 0
+# finally, wait for the background report generation to finish
+for pid in $pids
+do
+ if wait $pid
+ then
+ echo "Finished $pid"
+ else
+ exit 1
+ fi
+done
diff --git a/tools/run_tests/build_csharp.sh b/tools/run_tests/build_csharp.sh
index 2c33351..6737d88 100755
--- a/tools/run_tests/build_csharp.sh
+++ b/tools/run_tests/build_csharp.sh
@@ -30,7 +30,7 @@
set -ex
-if [ "$CONFIG" = "dbg" ] || [ "$CONFIG" = "gcov" ]
+if [ "$CONFIG" = "dbg" ]
then
MSBUILD_CONFIG="Debug"
else
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index fdbddf8..48afbaf 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -273,7 +273,7 @@
update_cache.finished(self._spec.identity(), self._bin_hash)
elif self._state == _RUNNING and time.time() - self._start > self._spec.timeout_seconds:
if self._timeout_retries < self._spec.timeout_retries:
- message('TIMEOUT_FLAKE', self._spec.shortname, stdout, do_newline=True)
+ message('TIMEOUT_FLAKE', '%s [pid=%d]' % (self._spec.shortname, self._process.pid), stdout, do_newline=True)
self._timeout_retries += 1
self.result.num_failures += 1
self.result.retries = self._timeout_retries + self._retries
@@ -282,7 +282,7 @@
self._process.terminate()
self.start()
else:
- message('TIMEOUT', self._spec.shortname, stdout, do_newline=True)
+ message('TIMEOUT', '%s [pid=%d]' % (self._spec.shortname, self._process.pid), stdout, do_newline=True)
self.kill()
self.result.state = 'TIMEOUT'
self.result.num_failures += 1
diff --git a/tools/run_tests/run_csharp.bat b/tools/run_tests/run_csharp.bat
index 0aa32ea..82eb585 100644
--- a/tools/run_tests/run_csharp.bat
+++ b/tools/run_tests/run_csharp.bat
@@ -6,16 +6,11 @@
cd /d %~dp0\..\..\src\csharp
if not "%CONFIG%" == "gcov" (
- @rem Run tests for assembly passed as 1st arg.
-
- @rem set UUID variable to a random GUID, we will use it to put TestResults.xml to a dedicated directory, so that parallel test runs don't collide
- for /F %%i in ('powershell -Command "[guid]::NewGuid().ToString()"') do (set UUID=%%i)
-
- packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe /domain:None -labels "%1/bin/Debug/%1.dll" -work test-results/%UUID% || goto :error
+ packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe %* || goto :error
) else (
@rem Run all tests with code coverage
- packages\OpenCover.4.6.166\tools\OpenCover.Console.exe -target:"packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe" -targetdir:"." -targetargs:"/domain:None -labels Grpc.Core.Tests/bin/Debug/Grpc.Core.Tests.dll Grpc.IntegrationTesting/bin/Debug/Grpc.IntegrationTesting.dll Grpc.Examples.Tests/bin/Debug/Grpc.Examples.Tests.dll Grpc.HealthCheck.Tests/bin/Debug/Grpc.HealthCheck.Tests.dll" -filter:"+[Grpc.Core]*" -register:user -output:coverage_results.xml || goto :error
+ packages\OpenCover.4.6.166\tools\OpenCover.Console.exe -target:"packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe" -targetdir:"." -targetargs:"%*" -filter:"+[Grpc.Core]*" -register:user -output:coverage_results.xml || goto :error
packages\ReportGenerator.2.3.2.0\tools\ReportGenerator.exe -reports:"coverage_results.xml" -targetdir:"..\..\reports\csharp_coverage" -reporttypes:"Html;TextSummary" || goto :error
diff --git a/tools/run_tests/run_csharp.sh b/tools/run_tests/run_csharp.sh
index 37e86fe..744df07 100755
--- a/tools/run_tests/run_csharp.sh
+++ b/tools/run_tests/run_csharp.sh
@@ -31,38 +31,25 @@
set -ex
CONFIG=${CONFIG:-opt}
-
NUNIT_CONSOLE="mono packages/NUnit.Runners.2.6.4/tools/nunit-console.exe"
-if [ "$CONFIG" = "dbg" ] || [ "$CONFIG" = "gcov" ]
-then
- MSBUILD_CONFIG="Debug"
-else
- MSBUILD_CONFIG="Release"
-fi
-
# change to gRPC repo root
cd $(dirname $0)/../..
-root=`pwd`
-export LD_LIBRARY_PATH=$root/libs/$CONFIG
+# path needs to be absolute
+export LD_LIBRARY_PATH=$(pwd)/libs/$CONFIG
+
+(cd src/csharp; $NUNIT_CONSOLE $@)
if [ "$CONFIG" = "gcov" ]
then
- (cd src/csharp; $NUNIT_CONSOLE -labels \
- "Grpc.Core.Tests/bin/$MSBUILD_CONFIG/Grpc.Core.Tests.dll" \
- "Grpc.Examples.Tests/bin/$MSBUILD_CONFIG/Grpc.Examples.Tests.dll" \
- "Grpc.HealthCheck.Tests/bin/$MSBUILD_CONFIG/Grpc.HealthCheck.Tests.dll" \
- "Grpc.IntegrationTesting/bin/$MSBUILD_CONFIG/Grpc.IntegrationTesting.dll")
-
+ # Generate the csharp extension coverage report
gcov objs/gcov/src/csharp/ext/*.o
lcov --base-directory . --directory . -c -o coverage.info
lcov -e coverage.info '**/src/csharp/ext/*' -o coverage.info
genhtml -o reports/csharp_ext_coverage --num-spaces 2 \
-t 'gRPC C# native extension test coverage' coverage.info \
--rc genhtml_hi_limit=95 --rc genhtml_med_limit=80 --no-prefix
-else
- (cd src/csharp; $NUNIT_CONSOLE -labels "$1/bin/$MSBUILD_CONFIG/$1.dll")
fi
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 006f4bc..3803e8c 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -47,6 +47,7 @@
import traceback
import time
import urllib2
+import uuid
import jobset
import report_utils
@@ -336,26 +337,42 @@
self.platform = platform_string()
def test_specs(self, config, args):
- assemblies = ['Grpc.Core.Tests',
- 'Grpc.Examples.Tests',
- 'Grpc.HealthCheck.Tests',
- 'Grpc.IntegrationTesting']
+ with open('src/csharp/tests.json') as f:
+ tests_json = json.load(f)
+ assemblies = tests_json['assemblies']
+ tests = tests_json['tests']
+
+ msbuild_config = _WINDOWS_CONFIG[config.build_config]
+ assembly_files = ['%s/bin/%s/%s.dll' % (a, msbuild_config, a)
+ for a in assemblies]
+
+ extra_args = ['-labels'] + assembly_files
+
if self.platform == 'windows':
- cmd = 'tools\\run_tests\\run_csharp.bat'
+ script_name = 'tools\\run_tests\\run_csharp.bat'
+ extra_args += ['-domain=None']
else:
- cmd = 'tools/run_tests/run_csharp.sh'
+ script_name = 'tools/run_tests/run_csharp.sh'
if config.build_config == 'gcov':
# On Windows, we only collect C# code coverage.
# On Linux, we only collect coverage for native extension.
# For code coverage all tests need to run as one suite.
- return [config.job_spec([cmd], None,
- environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
+ return [config.job_spec([script_name] + extra_args, None,
+ shortname='csharp.coverage',
+ environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
else:
- return [config.job_spec([cmd, assembly],
- None, shortname=assembly,
- environ=_FORCE_ENVIRON_FOR_WRAPPERS)
- for assembly in assemblies]
+ specs = []
+ for test in tests:
+ cmdline = [script_name, '-run=%s' % test] + extra_args
+ if self.platform == 'windows':
+ # use different output directory for each test to prevent
+ # TestResult.xml clash between parallel test runs.
+ cmdline += ['-work=test-result/%s' % uuid.uuid4()]
+ specs.append(config.job_spec(cmdline, None,
+ shortname='csharp.%s' % test,
+ environ=_FORCE_ENVIRON_FOR_WRAPPERS))
+ return specs
def pre_build_steps(self):
if self.platform == 'windows':
@@ -509,6 +526,7 @@
_WINDOWS_CONFIG = {
'dbg': 'Debug',
'opt': 'Release',
+ 'gcov': 'Release',
}
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 2ea8715..5cd1b2c 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -17257,6 +17257,21 @@
],
"headers": [],
"language": "c",
+ "name": "server_registered_method_bad_client_test",
+ "src": [
+ "test/core/bad_client/tests/server_registered_method.c"
+ ]
+ },
+ {
+ "deps": [
+ "bad_client_test",
+ "gpr",
+ "gpr_test_util",
+ "grpc_test_util_unsecure",
+ "grpc_unsecure"
+ ],
+ "headers": [],
+ "language": "c",
"name": "simple_request_bad_client_test",
"src": [
"test/core/bad_client/tests/simple_request.c"
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index 5f75acc..1107899 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -18402,6 +18402,24 @@
"exclude_configs": [],
"flaky": false,
"language": "c",
+ "name": "server_registered_method_bad_client_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ]
+ },
+ {
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "exclude_configs": [],
+ "flaky": false,
+ "language": "c",
"name": "simple_request_bad_client_test",
"platforms": [
"linux",
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index 5e5302a..7225f14 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -10903,6 +10903,18 @@
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server_registered_method_bad_client_test", "vcxproj\test\server_registered_method_bad_client_test\server_registered_method_bad_client_test.vcxproj", "{B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}"
+ ProjectSection(myProperties) = preProject
+ lib = "False"
+ EndProjectSection
+ ProjectSection(ProjectDependencies) = postProject
+ {BA67B418-B699-E41A-9CC4-0279C49481A5} = {BA67B418-B699-E41A-9CC4-0279C49481A5}
+ {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
+ {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+ {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+ {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+ EndProjectSection
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple_request_bad_client_test", "vcxproj\test\simple_request_bad_client_test\simple_request_bad_client_test.vcxproj", "{63422647-93FA-46BB-4827-95473D9D503C}"
ProjectSection(myProperties) = preProject
lib = "False"
@@ -24347,6 +24359,22 @@
{6756895E-05BF-8CC7-58F2-868DF0C0300C}.Release-DLL|Win32.Build.0 = Release|Win32
{6756895E-05BF-8CC7-58F2-868DF0C0300C}.Release-DLL|x64.ActiveCfg = Release|x64
{6756895E-05BF-8CC7-58F2-868DF0C0300C}.Release-DLL|x64.Build.0 = Release|x64
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Debug|x64.ActiveCfg = Debug|x64
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Release|Win32.ActiveCfg = Release|Win32
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Release|x64.ActiveCfg = Release|x64
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Debug|Win32.Build.0 = Debug|Win32
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Debug|x64.Build.0 = Debug|x64
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Release|Win32.Build.0 = Release|Win32
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Release|x64.Build.0 = Release|x64
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Debug-DLL|Win32.Build.0 = Debug|Win32
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Debug-DLL|x64.ActiveCfg = Debug|x64
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Debug-DLL|x64.Build.0 = Debug|x64
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Release-DLL|Win32.ActiveCfg = Release|Win32
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Release-DLL|Win32.Build.0 = Release|Win32
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Release-DLL|x64.ActiveCfg = Release|x64
+ {B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}.Release-DLL|x64.Build.0 = Release|x64
{63422647-93FA-46BB-4827-95473D9D503C}.Debug|Win32.ActiveCfg = Debug|Win32
{63422647-93FA-46BB-4827-95473D9D503C}.Debug|x64.ActiveCfg = Debug|x64
{63422647-93FA-46BB-4827-95473D9D503C}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/vcxproj/test/server_registered_method_bad_client_test/server_registered_method_bad_client_test.vcxproj b/vsprojects/vcxproj/test/server_registered_method_bad_client_test/server_registered_method_bad_client_test.vcxproj
new file mode 100644
index 0000000..6f8b7eb
--- /dev/null
+++ b/vsprojects/vcxproj/test/server_registered_method_bad_client_test/server_registered_method_bad_client_test.vcxproj
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{B4E7CD82-988A-BD3A-29F8-8590D3A8BC28}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="..\..\..\..\vsprojects\global.props" />
+ <Import Project="..\..\..\..\vsprojects\openssl.props" />
+ <Import Project="..\..\..\..\vsprojects\winsock.props" />
+ <Import Project="..\..\..\..\vsprojects\zlib.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+ <TargetName>server_registered_method_bad_client_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'">
+ <TargetName>server_registered_method_bad_client_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\test\core\bad_client\tests\server_registered_method.c">
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\bad_client_test\bad_client_test.vcxproj">
+ <Project>{BA67B418-B699-E41A-9CC4-0279C49481A5}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+ <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+ <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+ <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+ <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ </ImportGroup>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+ <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+ <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+ <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+ <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+ </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/server_registered_method_bad_client_test/server_registered_method_bad_client_test.vcxproj.filters b/vsprojects/vcxproj/test/server_registered_method_bad_client_test/server_registered_method_bad_client_test.vcxproj.filters
new file mode 100644
index 0000000..c74aa2e
--- /dev/null
+++ b/vsprojects/vcxproj/test/server_registered_method_bad_client_test/server_registered_method_bad_client_test.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\test\core\bad_client\tests\server_registered_method.c">
+ <Filter>test\core\bad_client\tests</Filter>
+ </ClCompile>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Filter Include="test">
+ <UniqueIdentifier>{e170992c-1d26-c352-1b77-0393c8e4de0d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\core">
+ <UniqueIdentifier>{aeb9b005-92ba-fd6b-8ad4-4cb18432e9e9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\core\bad_client">
+ <UniqueIdentifier>{a9ea2e08-63e8-2585-98db-9f2c0e409b60}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\core\bad_client\tests">
+ <UniqueIdentifier>{3a014dca-e8b5-bd9e-3ce0-64ced4d31a36}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
+