diff options
34 files changed, 1398 insertions, 113 deletions
@@ -833,6 +833,7 @@ hpack_table_test: $(BINDIR)/$(CONFIG)/hpack_table_test httpcli_format_request_test: $(BINDIR)/$(CONFIG)/httpcli_format_request_test httpcli_parser_test: $(BINDIR)/$(CONFIG)/httpcli_parser_test httpcli_test: $(BINDIR)/$(CONFIG)/httpcli_test +httpscli_test: $(BINDIR)/$(CONFIG)/httpscli_test init_test: $(BINDIR)/$(CONFIG)/init_test invalid_call_argument_test: $(BINDIR)/$(CONFIG)/invalid_call_argument_test json_rewrite: $(BINDIR)/$(CONFIG)/json_rewrite @@ -847,6 +848,7 @@ murmur_hash_test: $(BINDIR)/$(CONFIG)/murmur_hash_test no_server_test: $(BINDIR)/$(CONFIG)/no_server_test resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test secure_endpoint_test: $(BINDIR)/$(CONFIG)/secure_endpoint_test +server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test set_initial_connect_string_test: $(BINDIR)/$(CONFIG)/set_initial_connect_string_test sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test @@ -1925,6 +1927,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/httpcli_format_request_test \ $(BINDIR)/$(CONFIG)/httpcli_parser_test \ $(BINDIR)/$(CONFIG)/httpcli_test \ + $(BINDIR)/$(CONFIG)/httpscli_test \ $(BINDIR)/$(CONFIG)/init_test \ $(BINDIR)/$(CONFIG)/invalid_call_argument_test \ $(BINDIR)/$(CONFIG)/json_rewrite \ @@ -1938,6 +1941,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/no_server_test \ $(BINDIR)/$(CONFIG)/resolve_address_test \ $(BINDIR)/$(CONFIG)/secure_endpoint_test \ + $(BINDIR)/$(CONFIG)/server_chttp2_test \ $(BINDIR)/$(CONFIG)/set_initial_connect_string_test \ $(BINDIR)/$(CONFIG)/sockaddr_utils_test \ $(BINDIR)/$(CONFIG)/tcp_client_posix_test \ @@ -2948,6 +2952,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/httpcli_parser_test || ( echo test httpcli_parser_test failed ; exit 1 ) $(E) "[RUN] Testing httpcli_test" $(Q) $(BINDIR)/$(CONFIG)/httpcli_test || ( echo test httpcli_test failed ; exit 1 ) + $(E) "[RUN] Testing httpscli_test" + $(Q) $(BINDIR)/$(CONFIG)/httpscli_test || ( echo test httpscli_test failed ; exit 1 ) $(E) "[RUN] Testing init_test" $(Q) $(BINDIR)/$(CONFIG)/init_test || ( echo test init_test failed ; exit 1 ) $(E) "[RUN] Testing invalid_call_argument_test" @@ -2972,6 +2978,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/resolve_address_test || ( echo test resolve_address_test failed ; exit 1 ) $(E) "[RUN] Testing secure_endpoint_test" $(Q) $(BINDIR)/$(CONFIG)/secure_endpoint_test || ( echo test secure_endpoint_test failed ; exit 1 ) + $(E) "[RUN] Testing server_chttp2_test" + $(Q) $(BINDIR)/$(CONFIG)/server_chttp2_test || ( echo test server_chttp2_test failed ; exit 1 ) $(E) "[RUN] Testing set_initial_connect_string_test" $(Q) $(BINDIR)/$(CONFIG)/set_initial_connect_string_test || ( echo test set_initial_connect_string_test failed ; exit 1 ) $(E) "[RUN] Testing sockaddr_utils_test" @@ -10798,6 +10806,35 @@ endif endif +HTTPSCLI_TEST_SRC = \ + test/core/httpcli/httpscli_test.c \ + +HTTPSCLI_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTPSCLI_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/httpscli_test: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/httpscli_test: $(HTTPSCLI_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(HTTPSCLI_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/httpscli_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/httpcli/httpscli_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +deps_httpscli_test: $(HTTPSCLI_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(HTTPSCLI_TEST_OBJS:.o=.dep) +endif +endif + + INIT_TEST_SRC = \ test/core/surface/init_test.c \ @@ -11204,6 +11241,35 @@ endif endif +SERVER_CHTTP2_TEST_SRC = \ + test/core/surface/server_chttp2_test.c \ + +SERVER_CHTTP2_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CHTTP2_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/server_chttp2_test: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/server_chttp2_test: $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/server_chttp2_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/surface/server_chttp2_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +deps_server_chttp2_test: $(SERVER_CHTTP2_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(SERVER_CHTTP2_TEST_OBJS:.o=.dep) +endif +endif + + SET_INITIAL_CONNECT_STRING_TEST_SRC = \ test/core/client_config/set_initial_connect_string_test.c \ diff --git a/build.yaml b/build.yaml index 2891b7e19e..a67e7d0e71 100644 --- a/build.yaml +++ b/build.yaml @@ -1357,6 +1357,18 @@ targets: - mac - linux - posix +- name: httpscli_test + build: test + language: c + src: + - test/core/httpcli/httpscli_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + platforms: + - linux - name: init_test build: test language: c @@ -1498,6 +1510,16 @@ targets: - grpc - gpr_test_util - gpr +- name: server_chttp2_test + build: test + language: c + src: + - test/core/surface/server_chttp2_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr - name: set_initial_connect_string_test build: test language: c diff --git a/include/grpc/support/cmdline.h b/include/grpc/support/cmdline.h index 028dac2955..3058cf905a 100644 --- a/include/grpc/support/cmdline.h +++ b/include/grpc/support/cmdline.h @@ -83,8 +83,12 @@ void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help, void gpr_cmdline_on_extra_arg( gpr_cmdline *cl, const char *name, const char *help, void (*on_extra_arg)(void *user_data, const char *arg), void *user_data); -/* Parse the command line */ -void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv); +/* Enable surviving failure: default behavior is to exit the process */ +void gpr_cmdline_set_survive_failure(gpr_cmdline *cl); +/* Parse the command line; returns 1 on success, on failure either dies + (by default) or returns 0 if gpr_cmdline_set_survive_failure() has been + called */ +int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv); /* Destroy the parser */ void gpr_cmdline_destroy(gpr_cmdline *cl); /* Get a string describing usage */ diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c index a87f1aa87b..b5cd8d8d2a 100644 --- a/src/core/httpcli/httpcli.c +++ b/src/core/httpcli/httpcli.c @@ -53,6 +53,7 @@ typedef struct { size_t next_address; grpc_endpoint *ep; char *host; + char *ssl_host_override; gpr_timespec deadline; int have_read_byte; const grpc_httpcli_handshaker *handshaker; @@ -106,6 +107,7 @@ static void finish(grpc_exec_ctx *exec_ctx, internal_request *req, } gpr_slice_unref(req->request_text); gpr_free(req->host); + gpr_free(req->ssl_host_override); grpc_iomgr_unregister_object(&req->iomgr_obj); gpr_slice_buffer_destroy(&req->incoming); gpr_slice_buffer_destroy(&req->outgoing); @@ -180,8 +182,10 @@ static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, int success) { next_address(exec_ctx, req); return; } - req->handshaker->handshake(exec_ctx, req, req->ep, req->host, - on_handshake_done); + req->handshaker->handshake( + exec_ctx, req, req->ep, + req->ssl_host_override ? req->ssl_host_override : req->host, + on_handshake_done); } static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) { @@ -231,6 +235,7 @@ static void internal_request_begin( gpr_slice_buffer_init(&req->outgoing); grpc_iomgr_register_object(&req->iomgr_obj, name); req->host = gpr_strdup(request->host); + req->ssl_host_override = gpr_strdup(request->ssl_host_override); grpc_pollset_set_add_pollset(exec_ctx, &req->context->pollset_set, req->pollset); diff --git a/src/core/httpcli/httpcli.h b/src/core/httpcli/httpcli.h index 6469c2f03e..30875d71f1 100644 --- a/src/core/httpcli/httpcli.h +++ b/src/core/httpcli/httpcli.h @@ -74,6 +74,8 @@ extern const grpc_httpcli_handshaker grpc_httpcli_ssl; typedef struct grpc_httpcli_request { /* The host name to connect to */ char *host; + /* The host to verify in the SSL handshake (or NULL) */ + char *ssl_host_override; /* The path of the resource to fetch */ char *path; /* Additional headers: count and key/values; the following are supplied diff --git a/src/core/support/cmdline.c b/src/core/support/cmdline.c index 87f60bca2e..b517f30b2d 100644 --- a/src/core/support/cmdline.c +++ b/src/core/support/cmdline.c @@ -62,11 +62,13 @@ struct gpr_cmdline { void (*extra_arg)(void *user_data, const char *arg); void *extra_arg_user_data; - void (*state)(gpr_cmdline *cl, char *arg); + int (*state)(gpr_cmdline *cl, char *arg); arg *cur_arg; + + int survive_failure; }; -static void normal_state(gpr_cmdline *cl, char *arg); +static int normal_state(gpr_cmdline *cl, char *arg); gpr_cmdline *gpr_cmdline_create(const char *description) { gpr_cmdline *cl = gpr_malloc(sizeof(gpr_cmdline)); @@ -78,6 +80,10 @@ gpr_cmdline *gpr_cmdline_create(const char *description) { return cl; } +void gpr_cmdline_set_survive_failure(gpr_cmdline *cl) { + cl->survive_failure = 1; +} + void gpr_cmdline_destroy(gpr_cmdline *cl) { while (cl->args) { arg *a = cl->args; @@ -185,16 +191,22 @@ char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0) { return tmp; } -static void print_usage_and_die(gpr_cmdline *cl) { +static int print_usage_and_die(gpr_cmdline *cl) { char *usage = gpr_cmdline_usage_string(cl, cl->argv0); fprintf(stderr, "%s", usage); gpr_free(usage); - exit(1); + if (!cl->survive_failure) { + exit(1); + } + return 0; } -static void extra_state(gpr_cmdline *cl, char *str) { - if (!cl->extra_arg) print_usage_and_die(cl); +static int extra_state(gpr_cmdline *cl, char *str) { + if (!cl->extra_arg) { + return print_usage_and_die(cl); + } cl->extra_arg(cl->extra_arg_user_data, str); + return 1; } static arg *find_arg(gpr_cmdline *cl, char *name) { @@ -208,13 +220,13 @@ static arg *find_arg(gpr_cmdline *cl, char *name) { if (!a) { fprintf(stderr, "Unknown argument: %s\n", name); - print_usage_and_die(cl); + return NULL; } return a; } -static void value_state(gpr_cmdline *cl, char *str) { +static int value_state(gpr_cmdline *cl, char *str) { long intval; char *end; @@ -226,7 +238,7 @@ static void value_state(gpr_cmdline *cl, char *str) { if (*end || intval < INT_MIN || intval > INT_MAX) { fprintf(stderr, "expected integer, got '%s' for %s\n", str, cl->cur_arg->name); - print_usage_and_die(cl); + return print_usage_and_die(cl); } *(int *)cl->cur_arg->value = (int)intval; break; @@ -238,7 +250,7 @@ static void value_state(gpr_cmdline *cl, char *str) { } else { fprintf(stderr, "expected boolean, got '%s' for %s\n", str, cl->cur_arg->name); - print_usage_and_die(cl); + return print_usage_and_die(cl); } break; case ARGTYPE_STRING: @@ -247,16 +259,18 @@ static void value_state(gpr_cmdline *cl, char *str) { } cl->state = normal_state; + return 1; } -static void normal_state(gpr_cmdline *cl, char *str) { +static int normal_state(gpr_cmdline *cl, char *str) { char *eq = NULL; char *tmp = NULL; char *arg_name = NULL; + int r = 1; if (0 == strcmp(str, "-help") || 0 == strcmp(str, "--help") || 0 == strcmp(str, "-h")) { - print_usage_and_die(cl); + return print_usage_and_die(cl); } cl->cur_arg = NULL; @@ -266,7 +280,7 @@ static void normal_state(gpr_cmdline *cl, char *str) { if (str[2] == 0) { /* handle '--' to move to just extra args */ cl->state = extra_state; - return; + return 1; } str += 2; } else { @@ -277,12 +291,15 @@ static void normal_state(gpr_cmdline *cl, char *str) { /* str is of the form '--no-foo' - it's a flag disable */ str += 3; cl->cur_arg = find_arg(cl, str); + if (cl->cur_arg == NULL) { + return print_usage_and_die(cl); + } if (cl->cur_arg->type != ARGTYPE_BOOL) { fprintf(stderr, "%s is not a flag argument\n", str); - print_usage_and_die(cl); + return print_usage_and_die(cl); } *(int *)cl->cur_arg->value = 0; - return; /* early out */ + return 1; /* early out */ } eq = strchr(str, '='); if (eq != NULL) { @@ -294,9 +311,12 @@ static void normal_state(gpr_cmdline *cl, char *str) { arg_name = str; } cl->cur_arg = find_arg(cl, arg_name); + if (cl->cur_arg == NULL) { + return print_usage_and_die(cl); + } if (eq != NULL) { /* str was of the type --foo=value, parse the value */ - value_state(cl, eq + 1); + r = value_state(cl, eq + 1); } else if (cl->cur_arg->type != ARGTYPE_BOOL) { /* flag types don't have a '--foo value' variant, other types do */ cl->state = value_state; @@ -305,19 +325,23 @@ static void normal_state(gpr_cmdline *cl, char *str) { *(int *)cl->cur_arg->value = 1; } } else { - extra_state(cl, str); + r = extra_state(cl, str); } gpr_free(tmp); + return r; } -void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) { +int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) { int i; GPR_ASSERT(argc >= 1); cl->argv0 = argv[0]; for (i = 1; i < argc; i++) { - cl->state(cl, argv[i]); + if (!cl->state(cl, argv[i])) { + return 0; + } } + return 1; } diff --git a/src/core/surface/server_chttp2.c b/src/core/surface/server_chttp2.c index 990bc4aa23..08691c858b 100644 --- a/src/core/surface/server_chttp2.c +++ b/src/core/surface/server_chttp2.c @@ -101,9 +101,7 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) { } tcp = grpc_tcp_server_create(); - if (!tcp) { - goto error; - } + GPR_ASSERT(tcp); for (i = 0; i < resolved->naddrs; i++) { grpc_tcp_listener *listener; diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c index 4328bdd684..df05d1a302 100644 --- a/src/core/transport/metadata.c +++ b/src/core/transport/metadata.c @@ -711,7 +711,7 @@ int grpc_mdstr_is_legal_header(grpc_mdstr *s) { int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s) { static const gpr_uint8 legal_header_bits[256 / 8] = { - 0x00, 0x00, 0x00, 0x00, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; return conforms_to(s, legal_header_bits); diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs index 0ade701a53..de66759b94 100644 --- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs +++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs @@ -284,7 +284,7 @@ namespace Grpc.Core.Internal var finishedTask = asyncCall.ServerSideCallAsync(); var responseStream = new ServerResponseStream<byte[], byte[]>(asyncCall); - await responseStream.WriteStatusAsync(new Status(StatusCode.Unimplemented, "No such method."), Metadata.Empty).ConfigureAwait(false); + await responseStream.WriteStatusAsync(new Status(StatusCode.Unimplemented, ""), Metadata.Empty).ConfigureAwait(false); await finishedTask.ConfigureAwait(false); } } diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index 5eec11abf7..b0e33e49f7 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -34,6 +34,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -130,8 +131,7 @@ namespace Grpc.IntegrationTesting }; } var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions); - TestService.TestServiceClient client = new TestService.TestServiceClient(channel); - await RunTestCaseAsync(client, options); + await RunTestCaseAsync(channel, options); await channel.ShutdownAsync(); } @@ -159,8 +159,9 @@ namespace Grpc.IntegrationTesting return credentials; } - private async Task RunTestCaseAsync(TestService.TestServiceClient client, ClientOptions options) + private async Task RunTestCaseAsync(Channel channel, ClientOptions options) { + var client = new TestService.TestServiceClient(channel); switch (options.TestCase) { case "empty_unary": @@ -202,8 +203,14 @@ namespace Grpc.IntegrationTesting case "timeout_on_sleeping_server": await RunTimeoutOnSleepingServerAsync(client); break; - case "benchmark_empty_unary": - RunBenchmarkEmptyUnary(client); + case "custom_metadata": + await RunCustomMetadataAsync(client); + break; + case "status_code_and_message": + await RunStatusCodeAndMessageAsync(client); + break; + case "unimplemented_method": + RunUnimplementedMethod(new UnimplementedService.UnimplementedServiceClient(channel)); break; default: throw new ArgumentException("Unknown test case " + options.TestCase); @@ -227,7 +234,6 @@ namespace Grpc.IntegrationTesting ResponseSize = 314159, Payload = CreateZerosPayload(271828) }; - var response = client.UnaryCall(request); Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); @@ -493,11 +499,95 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - // This is not an official interop test, but it's useful. - public static void RunBenchmarkEmptyUnary(TestService.ITestServiceClient client) + public static async Task RunCustomMetadataAsync(TestService.ITestServiceClient client) { - BenchmarkUtil.RunBenchmark(10000, 10000, - () => { client.EmptyCall(new Empty()); }); + Console.WriteLine("running custom_metadata"); + { + // step 1: test unary call + var request = new SimpleRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseSize = 314159, + Payload = CreateZerosPayload(271828) + }; + + var call = client.UnaryCallAsync(request, headers: CreateTestMetadata()); + await call.ResponseAsync; + + var responseHeaders = await call.ResponseHeadersAsync; + var responseTrailers = call.GetTrailers(); + + Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value); + CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes); + } + + { + // step 2: test full duplex call + var request = new StreamingOutputCallRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseParameters = { new ResponseParameters { Size = 31415 } }, + Payload = CreateZerosPayload(27182) + }; + + var call = client.FullDuplexCall(headers: CreateTestMetadata()); + var responseHeaders = await call.ResponseHeadersAsync; + + await call.RequestStream.WriteAsync(request); + await call.RequestStream.CompleteAsync(); + await call.ResponseStream.ToListAsync(); + + var responseTrailers = call.GetTrailers(); + + Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value); + CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes); + } + + Console.WriteLine("Passed!"); + } + + public static async Task RunStatusCodeAndMessageAsync(TestService.ITestServiceClient client) + { + Console.WriteLine("running status_code_and_message"); + var echoStatus = new EchoStatus + { + Code = 2, + Message = "test status message" + }; + + { + // step 1: test unary call + var request = new SimpleRequest { ResponseStatus = echoStatus }; + + var e = Assert.Throws<RpcException>(() => client.UnaryCall(request)); + Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); + Assert.AreEqual(echoStatus.Message, e.Status.Detail); + } + + { + // step 2: test full duplex call + var request = new StreamingOutputCallRequest { ResponseStatus = echoStatus }; + + var call = client.FullDuplexCall(); + await call.RequestStream.WriteAsync(request); + await call.RequestStream.CompleteAsync(); + + var e = Assert.Throws<RpcException>(async () => await call.ResponseStream.ToListAsync()); + Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); + Assert.AreEqual(echoStatus.Message, e.Status.Detail); + } + + Console.WriteLine("Passed!"); + } + + public static void RunUnimplementedMethod(UnimplementedService.IUnimplementedServiceClient client) + { + Console.WriteLine("running unimplemented_method"); + var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty())); + + Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode); + Assert.AreEqual("", e.Status.Detail); + Console.WriteLine("Passed!"); } private static Payload CreateZerosPayload(int size) @@ -516,5 +606,14 @@ namespace Grpc.IntegrationTesting Assert.IsTrue(email.Length > 0); // spec requires nonempty client email. return email; } + + private static Metadata CreateTestMetadata() + { + return new Metadata + { + {"x-grpc-test-echo-initial", "test_initial_metadata_value"}, + {"x-grpc-test-echo-trailing-bin", new byte[] {0xab, 0xab, 0xab}} + }; + } } } diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs index 837ae74c45..5facb87971 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs @@ -128,9 +128,27 @@ namespace Grpc.IntegrationTesting } [Test] - public async Task TimeoutOnSleepingServerAsync() + public async Task TimeoutOnSleepingServer() { await InteropClient.RunTimeoutOnSleepingServerAsync(client); } + + [Test] + public async Task CustomMetadata() + { + await InteropClient.RunCustomMetadataAsync(client); + } + + [Test] + public async Task StatusCodeAndMessage() + { + await InteropClient.RunStatusCodeAndMessageAsync(client); + } + + [Test] + public void UnimplementedMethod() + { + InteropClient.RunUnimplementedMethod(UnimplementedService.NewClient(channel)); + } } } diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs index c5bfcf08c0..5a1b4cf319 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; @@ -51,14 +52,20 @@ namespace Grpc.Testing return Task.FromResult(new Empty()); } - public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context) + public async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context) { + await EnsureEchoMetadataAsync(context); + EnsureEchoStatus(request.ResponseStatus, context); + var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; - return Task.FromResult(response); + return response; } public async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) { + await EnsureEchoMetadataAsync(context); + EnsureEchoStatus(request.ResponseStatus, context); + foreach (var responseParam in request.ResponseParameters) { var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; @@ -68,6 +75,8 @@ namespace Grpc.Testing public async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context) { + await EnsureEchoMetadataAsync(context); + int sum = 0; await requestStream.ForEachAsync(async request => { @@ -78,8 +87,11 @@ namespace Grpc.Testing public async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) { + await EnsureEchoMetadataAsync(context); + await requestStream.ForEachAsync(async request => { + EnsureEchoStatus(request.ResponseStatus, context); foreach (var responseParam in request.ResponseParameters) { var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; @@ -97,5 +109,28 @@ namespace Grpc.Testing { return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; } + + private static async Task EnsureEchoMetadataAsync(ServerCallContext context) + { + var echoInitialList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-initial").ToList(); + if (echoInitialList.Any()) { + var entry = echoInitialList.Single(); + await context.WriteResponseHeadersAsync(new Metadata { entry }); + } + + var echoTrailingList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ToList(); + if (echoTrailingList.Any()) { + context.ResponseTrailers.Add(echoTrailingList.Single()); + } + } + + private static void EnsureEchoStatus(EchoStatus responseStatus, ServerCallContext context) + { + if (responseStatus != null) + { + var statusCode = (StatusCode)responseStatus.Code; + context.Status = new Status(statusCode, responseStatus.Message); + } + } } } diff --git a/src/node/ext/channel_credentials.cc b/src/node/ext/channel_credentials.cc index b77ff80af2..059bc8a890 100644 --- a/src/node/ext/channel_credentials.cc +++ b/src/node/ext/channel_credentials.cc @@ -154,6 +154,12 @@ NAN_METHOD(ChannelCredentials::CreateSsl) { return Nan::ThrowTypeError( "createSSl's third argument must be a Buffer if provided"); } + if ((key_cert_pair.private_key == NULL) != + (key_cert_pair.cert_chain == NULL)) { + return Nan::ThrowError( + "createSsl's second and third arguments must be" + " provided or omitted together"); + } grpc_channel_credentials *creds = grpc_ssl_credentials_create( root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair, NULL); diff --git a/src/node/ext/server_credentials.cc b/src/node/ext/server_credentials.cc index e6c55e263c..5285d53df4 100644 --- a/src/node/ext/server_credentials.cc +++ b/src/node/ext/server_credentials.cc @@ -167,30 +167,18 @@ NAN_METHOD(ServerCredentials::CreateSsl) { return Nan::ThrowTypeError("Key/cert pairs must be objects"); } Local<Object> pair_obj = Nan::To<Object>(pair_val).ToLocalChecked(); - MaybeLocal<Value> maybe_key = Nan::Get(pair_obj, key_key); - if (maybe_key.IsEmpty()) { - delete key_cert_pairs; - return Nan::ThrowTypeError( - "Key/cert pairs must have a private_key and a cert_chain"); - } - MaybeLocal<Value> maybe_cert = Nan::Get(pair_obj, cert_key); - if (maybe_cert.IsEmpty()) { - delete key_cert_pairs; - return Nan::ThrowTypeError( - "Key/cert pairs must have a private_key and a cert_chain"); - } - if (!::node::Buffer::HasInstance(maybe_key.ToLocalChecked())) { + Local<Value> maybe_key = Nan::Get(pair_obj, key_key).ToLocalChecked(); + Local<Value> maybe_cert = Nan::Get(pair_obj, cert_key).ToLocalChecked(); + if (!::node::Buffer::HasInstance(maybe_key)) { delete key_cert_pairs; return Nan::ThrowTypeError("private_key must be a Buffer"); } - if (!::node::Buffer::HasInstance(maybe_cert.ToLocalChecked())) { + if (!::node::Buffer::HasInstance(maybe_cert)) { delete key_cert_pairs; return Nan::ThrowTypeError("cert_chain must be a Buffer"); } - key_cert_pairs[i].private_key = ::node::Buffer::Data( - maybe_key.ToLocalChecked()); - key_cert_pairs[i].cert_chain = ::node::Buffer::Data( - maybe_cert.ToLocalChecked()); + key_cert_pairs[i].private_key = ::node::Buffer::Data(maybe_key); + key_cert_pairs[i].cert_chain = ::node::Buffer::Data(maybe_cert); } grpc_server_credentials *creds = grpc_ssl_server_credentials_create( root_certs, key_cert_pairs, key_cert_pair_count, force_client_auth, NULL); diff --git a/src/node/test/credentials_test.js b/src/node/test/credentials_test.js index 647f648ca9..294600c85a 100644 --- a/src/node/test/credentials_test.js +++ b/src/node/test/credentials_test.js @@ -76,6 +76,146 @@ var fakeFailingGoogleCredentials = { } }; +var key_data, pem_data, ca_data; + +before(function() { + var key_path = path.join(__dirname, './data/server1.key'); + var pem_path = path.join(__dirname, './data/server1.pem'); + var ca_path = path.join(__dirname, '../test/data/ca.pem'); + key_data = fs.readFileSync(key_path); + pem_data = fs.readFileSync(pem_path); + ca_data = fs.readFileSync(ca_path); +}); + +describe('channel credentials', function() { + describe('#createSsl', function() { + it('works with no arguments', function() { + var creds; + assert.doesNotThrow(function() { + creds = grpc.credentials.createSsl(); + }); + assert.notEqual(creds, null); + }); + it('works with just one Buffer argument', function() { + var creds; + assert.doesNotThrow(function() { + creds = grpc.credentials.createSsl(ca_data); + }); + assert.notEqual(creds, null); + }); + it('works with 3 Buffer arguments', function() { + var creds; + assert.doesNotThrow(function() { + creds = grpc.credentials.createSsl(ca_data, key_data, pem_data); + }); + assert.notEqual(creds, null); + }); + it('works if the first argument is null', function() { + var creds; + assert.doesNotThrow(function() { + creds = grpc.credentials.createSsl(null, key_data, pem_data); + }); + assert.notEqual(creds, null); + }); + it('fails if the first argument is a non-Buffer value', function() { + assert.throws(function() { + grpc.credentials.createSsl('test'); + }, TypeError); + }); + it('fails if the second argument is a non-Buffer value', function() { + assert.throws(function() { + grpc.credentials.createSsl(null, 'test', pem_data); + }, TypeError); + }); + it('fails if the third argument is a non-Buffer value', function() { + assert.throws(function() { + grpc.credentials.createSsl(null, key_data, 'test'); + }, TypeError); + }); + it('fails if only 1 of the last 2 arguments is provided', function() { + assert.throws(function() { + grpc.credentials.createSsl(null, key_data); + }); + assert.throws(function() { + grpc.credentials.createSsl(null, null, pem_data); + }); + }); + }); +}); + +describe('server credentials', function() { + describe('#createSsl', function() { + it('accepts a buffer and array as the first 2 arguments', function() { + var creds; + assert.doesNotThrow(function() { + creds = grpc.ServerCredentials.createSsl(ca_data, []); + }); + assert.notEqual(creds, null); + }); + it('accepts a boolean as the third argument', function() { + var creds; + assert.doesNotThrow(function() { + creds = grpc.ServerCredentials.createSsl(ca_data, [], true); + }); + assert.notEqual(creds, null); + }); + it('accepts an object with two buffers in the second argument', function() { + var creds; + assert.doesNotThrow(function() { + creds = grpc.ServerCredentials.createSsl(null, + [{private_key: key_data, + cert_chain: pem_data}]); + }); + assert.notEqual(creds, null); + }); + it('accepts multiple objects in the second argument', function() { + var creds; + assert.doesNotThrow(function() { + creds = grpc.ServerCredentials.createSsl(null, + [{private_key: key_data, + cert_chain: pem_data}, + {private_key: key_data, + cert_chain: pem_data}]); + }); + assert.notEqual(creds, null); + }); + it('fails if the second argument is not an Array', function() { + assert.throws(function() { + grpc.ServerCredentials.createSsl(ca_data, 'test'); + }, TypeError); + }); + it('fails if the first argument is a non-Buffer value', function() { + assert.throws(function() { + grpc.ServerCredentials.createSsl('test', []); + }, TypeError); + }); + it('fails if the third argument is a non-boolean value', function() { + assert.throws(function() { + grpc.ServerCredentials.createSsl(ca_data, [], 'test'); + }, TypeError); + }); + it('fails if the array elements are not objects', function() { + assert.throws(function() { + grpc.ServerCredentials.createSsl(ca_data, 'test'); + }, TypeError); + }); + it('fails if the object does not have a Buffer private_key', function() { + assert.throws(function() { + grpc.ServerCredentials.createSsl(null, + [{private_key: 'test', + cert_chain: pem_data}]); + }, TypeError); + }); + it('fails if the object does not have a Buffer cert_chain', function() { + assert.throws(function() { + grpc.ServerCredentials.createSsl(null, + [{private_key: key_data, + cert_chain: 'test'}]); + }, TypeError); + }); + }); +}); + describe('client credentials', function() { var Client; var server; @@ -109,20 +249,13 @@ describe('client credentials', function() { }); } }); - var key_path = path.join(__dirname, './data/server1.key'); - var pem_path = path.join(__dirname, './data/server1.pem'); - var key_data = fs.readFileSync(key_path); - var pem_data = fs.readFileSync(pem_path); var creds = grpc.ServerCredentials.createSsl(null, [{private_key: key_data, cert_chain: pem_data}]); - //creds = grpc.ServerCredentials.createInsecure(); port = server.bind('localhost:0', creds); server.start(); Client = proto.TestService; - var ca_path = path.join(__dirname, '../test/data/ca.pem'); - var ca_data = fs.readFileSync(ca_path); client_ssl_creds = grpc.credentials.createSsl(ca_data); var host_override = 'foo.test.google.fr'; client_options['grpc.ssl_target_name_override'] = host_override; diff --git a/src/node/test/server_test.js b/src/node/test/server_test.js index 999a183b3c..592f47e145 100644 --- a/src/node/test/server_test.js +++ b/src/node/test/server_test.js @@ -45,9 +45,30 @@ describe('server', function() { new grpc.Server(); }); }); - it('should work with an empty list argument', function() { + it('should work with an empty object argument', function() { assert.doesNotThrow(function() { - new grpc.Server([]); + new grpc.Server({}); + }); + }); + it('should work without the new keyword', function() { + var server; + assert.doesNotThrow(function() { + server = grpc.Server(); + }); + assert(server instanceof grpc.Server); + }); + it('should only accept objects with string or int values', function() { + assert.doesNotThrow(function() { + new grpc.Server({'key' : 'value'}); + }); + assert.doesNotThrow(function() { + new grpc.Server({'key' : 5}); + }); + assert.throws(function() { + new grpc.Server({'key' : null}); + }); + assert.throws(function() { + new grpc.Server({'key' : new Date()}); }); }); }); diff --git a/test/core/bad_client/tests/initial_settings_frame.c b/test/core/bad_client/tests/initial_settings_frame.c index 129c667f71..17ad99df4e 100644 --- a/test/core/bad_client/tests/initial_settings_frame.c +++ b/test/core/bad_client/tests/initial_settings_frame.c @@ -103,6 +103,19 @@ int main(int argc, char **argv) { GRPC_RUN_BAD_CLIENT_TEST(verifier, PFX_STR ONE_SETTING_HDR "\x00\x04\x00\x01\x00\x00", GRPC_BAD_CLIENT_DISCONNECT); + /* ack with data */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, + PFX_STR + "\x00\x00\x00\x04\x00\x00\x00\x00\x00" + "\x00\x00\x01\x04\x01\x00\x00\x00\x00", 0); + /* settings frame with invalid flags */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, + PFX_STR + "\x00\x00\x00\x04\x10\x00\x00\x00\x00", 0); + /* unknown settings should be ignored */ + GRPC_RUN_BAD_CLIENT_TEST(verifier, + PFX_STR ONE_SETTING_HDR "\x00\x99\x00\x00\x00\x00", + GRPC_BAD_CLIENT_DISCONNECT); return 0; } diff --git a/test/core/httpcli/httpcli_test.c b/test/core/httpcli/httpcli_test.c index 4012f995c7..d47774251a 100644 --- a/test/core/httpcli/httpcli_test.c +++ b/test/core/httpcli/httpcli_test.c @@ -69,13 +69,13 @@ static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); } -static void test_get(int use_ssl, int port) { +static void test_get(int port) { grpc_httpcli_request req; char *host; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; g_done = 0; - gpr_log(GPR_INFO, "running %s with use_ssl=%d.", "test_get", use_ssl); + gpr_log(GPR_INFO, "test_get"); gpr_asprintf(&host, "localhost:%d", port); gpr_log(GPR_INFO, "requesting from %s", host); @@ -83,7 +83,7 @@ static void test_get(int use_ssl, int port) { memset(&req, 0, sizeof(req)); req.host = host; req.path = "/get"; - req.handshaker = use_ssl ? &grpc_httpcli_ssl : &grpc_httpcli_plaintext; + req.handshaker = &grpc_httpcli_plaintext; grpc_httpcli_get(&exec_ctx, &g_context, &g_pollset, &req, n_seconds_time(15), on_finish, (void *)42); @@ -100,13 +100,13 @@ static void test_get(int use_ssl, int port) { gpr_free(host); } -static void test_post(int use_ssl, int port) { +static void test_post(int port) { grpc_httpcli_request req; char *host; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; g_done = 0; - gpr_log(GPR_INFO, "running %s with use_ssl=%d.", "test_post", (int)use_ssl); + gpr_log(GPR_INFO, "test_post"); gpr_asprintf(&host, "localhost:%d", port); gpr_log(GPR_INFO, "posting to %s", host); @@ -114,7 +114,7 @@ static void test_post(int use_ssl, int port) { memset(&req, 0, sizeof(req)); req.host = host; req.path = "/post"; - req.handshaker = use_ssl ? &grpc_httpcli_ssl : &grpc_httpcli_plaintext; + req.handshaker = &grpc_httpcli_plaintext; grpc_httpcli_post(&exec_ctx, &g_context, &g_pollset, &req, "hello", 5, n_seconds_time(15), on_finish, (void *)42); @@ -170,8 +170,8 @@ int main(int argc, char **argv) { grpc_httpcli_context_init(&g_context); grpc_pollset_init(&g_pollset); - test_get(0, port); - test_post(0, port); + test_get(port); + test_post(port); grpc_httpcli_context_destroy(&g_context); grpc_closure_init(&destroyed, destroy_pollset, &g_pollset); diff --git a/test/core/httpcli/httpscli_test.c b/test/core/httpcli/httpscli_test.c new file mode 100644 index 0000000000..b1c1913cae --- /dev/null +++ b/test/core/httpcli/httpscli_test.c @@ -0,0 +1,188 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/httpcli/httpcli.h" + +#include <string.h> + +#include <grpc/grpc.h> +#include "src/core/iomgr/iomgr.h" +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/subprocess.h> +#include <grpc/support/sync.h> +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static int g_done = 0; +static grpc_httpcli_context g_context; +static grpc_pollset g_pollset; + +static gpr_timespec n_seconds_time(int seconds) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds); +} + +static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, + const grpc_httpcli_response *response) { + const char *expect = + "<html><head><title>Hello world!</title></head>" + "<body><p>This is a test</p></body></html>"; + GPR_ASSERT(arg == (void *)42); + GPR_ASSERT(response); + GPR_ASSERT(response->status == 200); + GPR_ASSERT(response->body_length == strlen(expect)); + GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length)); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + g_done = 1; + grpc_pollset_kick(&g_pollset, NULL); + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); +} + +static void test_get(int port) { + grpc_httpcli_request req; + char *host; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + g_done = 0; + gpr_log(GPR_INFO, "test_get"); + + gpr_asprintf(&host, "localhost:%d", port); + gpr_log(GPR_INFO, "requesting from %s", host); + + memset(&req, 0, sizeof(req)); + req.host = host; + req.ssl_host_override = "foo.test.google.fr"; + req.path = "/get"; + req.handshaker = &grpc_httpcli_ssl; + + grpc_httpcli_get(&exec_ctx, &g_context, &g_pollset, &req, n_seconds_time(15), + on_finish, (void *)42); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + while (!g_done) { + grpc_pollset_worker worker; + grpc_pollset_work(&exec_ctx, &g_pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20)); + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + } + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + gpr_free(host); +} + +static void test_post(int port) { + grpc_httpcli_request req; + char *host; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + g_done = 0; + gpr_log(GPR_INFO, "test_post"); + + gpr_asprintf(&host, "localhost:%d", port); + gpr_log(GPR_INFO, "posting to %s", host); + + memset(&req, 0, sizeof(req)); + req.host = host; + req.ssl_host_override = "foo.test.google.fr"; + req.path = "/post"; + req.handshaker = &grpc_httpcli_ssl; + + grpc_httpcli_post(&exec_ctx, &g_context, &g_pollset, &req, "hello", 5, + n_seconds_time(15), on_finish, (void *)42); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + while (!g_done) { + grpc_pollset_worker worker; + grpc_pollset_work(&exec_ctx, &g_pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20)); + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + grpc_exec_ctx_finish(&exec_ctx); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + } + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + gpr_free(host); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, int success) { + grpc_pollset_destroy(p); +} + +int main(int argc, char **argv) { + grpc_closure destroyed; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_subprocess *server; + char *me = argv[0]; + char *lslash = strrchr(me, '/'); + char *args[5]; + char root[1024]; + int port = grpc_pick_unused_port_or_die(); + + /* figure out where we are */ + if (lslash) { + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + strcpy(root, "."); + } + + /* start the server */ + gpr_asprintf(&args[0], "%s/../../test/core/httpcli/test_server.py", root); + args[1] = "--port"; + gpr_asprintf(&args[2], "%d", port); + args[3] = "--ssl"; + server = gpr_subprocess_create(4, (const char **)args); + GPR_ASSERT(server); + gpr_free(args[0]); + gpr_free(args[2]); + + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(5, GPR_TIMESPAN))); + + grpc_test_init(argc, argv); + grpc_init(); + grpc_httpcli_context_init(&g_context); + grpc_pollset_init(&g_pollset); + + test_get(port); + test_post(port); + + grpc_httpcli_context_destroy(&g_context); + grpc_closure_init(&destroyed, destroy_pollset, &g_pollset); + grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); + + gpr_subprocess_destroy(server); + + return 0; +} diff --git a/test/core/httpcli/test_server.py b/test/core/httpcli/test_server.py index 4aaf5e30f8..225c2a6b0f 100755 --- a/test/core/httpcli/test_server.py +++ b/test/core/httpcli/test_server.py @@ -4,9 +4,18 @@ import argparse import BaseHTTPServer +import os +import ssl +import sys + +_PEM = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/tsi/test_creds/server1.pem')) +_KEY = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..', 'src/core/tsi/test_creds/server1.key')) +print _PEM +open(_PEM).close() argp = argparse.ArgumentParser(description='Server for httpcli_test') argp.add_argument('-p', '--port', default=10080, type=int) +argp.add_argument('-s', '--ssl', default=False, action='store_true') args = argp.parse_args() print 'server running on port %d' % args.port @@ -28,4 +37,7 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler): if self.path == '/post' and content == 'hello': self.good() -BaseHTTPServer.HTTPServer(('', args.port), Handler).serve_forever() +httpd = BaseHTTPServer.HTTPServer(('localhost', args.port), Handler) +if args.ssl: + httpd.socket = ssl.wrap_socket(httpd.socket, certfile=_PEM, keyfile=_KEY, server_side=True) +httpd.serve_forever() diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index d6febf586e..5eb6118057 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -1096,6 +1096,7 @@ static void test_get_well_known_google_credentials_file_path(void) { int main(int argc, char **argv) { grpc_test_init(argc, argv); + grpc_init(); test_empty_md_store(); test_ref_unref_empty_md_store(); test_add_to_empty_md_store(); @@ -1126,5 +1127,6 @@ int main(int argc, char **argv) { test_metadata_plugin_success(); test_metadata_plugin_failure(); test_get_well_known_google_credentials_file_path(); + grpc_shutdown(); return 0; } diff --git a/test/core/support/cmdline_test.c b/test/core/support/cmdline_test.c index 1c77c15233..4730fcc1b5 100644 --- a/test/core/support/cmdline_test.c +++ b/test/core/support/cmdline_test.c @@ -40,7 +40,7 @@ #include <grpc/support/useful.h> #include "test/core/util/test_config.h" -#define LOG_TEST() gpr_log(GPR_INFO, "%s", __FILE__) +#define LOG_TEST() gpr_log(GPR_INFO, "test at %s:%d", __FILE__, __LINE__) static void test_simple_int(void) { int x = 1; @@ -273,6 +273,44 @@ static void test_many(void) { gpr_cmdline_destroy(cl); } +static void extra_arg_cb(void *user_data, const char *arg) { + int *count = user_data; + GPR_ASSERT(arg != NULL); + GPR_ASSERT(strlen(arg) == 1); + GPR_ASSERT(arg[0] == 'a' + *count); + ++*count; +} + +static void test_extra(void) { + gpr_cmdline *cl; + int count = 0; + char *args[] = {(char *)__FILE__, "a", "b", "c"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + &count); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(count == 3); + gpr_cmdline_destroy(cl); +} + +static void test_extra_dashdash(void) { + gpr_cmdline *cl; + int count = 0; + char *args[] = {(char *)__FILE__, "--", "a", "b", "c"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + &count); + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args); + GPR_ASSERT(count == 3); + gpr_cmdline_destroy(cl); +} + static void test_usage(void) { gpr_cmdline *cl; char *usage; @@ -281,20 +319,154 @@ static void test_usage(void) { int x = 0; int flag = 2; + LOG_TEST(); + cl = gpr_cmdline_create(NULL); gpr_cmdline_add_string(cl, "str", NULL, &str); gpr_cmdline_add_int(cl, "x", NULL, &x); gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); usage = gpr_cmdline_usage_string(cl, "test"); - GPR_ASSERT( - 0 == strcmp(usage, - "Usage: test [--str=string] [--x=int] [--flag|--no-flag]\n")); + GPR_ASSERT(0 == strcmp(usage, + "Usage: test [--str=string] [--x=int] " + "[--flag|--no-flag] [file...]\n")); + gpr_free(usage); + + usage = gpr_cmdline_usage_string(cl, "/foo/test"); + GPR_ASSERT(0 == strcmp(usage, + "Usage: test [--str=string] [--x=int] " + "[--flag|--no-flag] [file...]\n")); gpr_free(usage); gpr_cmdline_destroy(cl); } +static void test_help(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *help[] = {(char *)__FILE__, "-h"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT(0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(help), help)); + + gpr_cmdline_destroy(cl); +} + +static void test_badargs1(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_arg_name[] = {(char *)__FILE__, "--y"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT(0 == + gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_arg_name), bad_arg_name)); + + gpr_cmdline_destroy(cl); +} + +static void test_badargs2(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_int_value[] = {(char *)__FILE__, "--x", "henry"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT( + 0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_int_value), bad_int_value)); + + gpr_cmdline_destroy(cl); +} + +static void test_badargs3(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_bool_value[] = {(char *)__FILE__, "--flag=henry"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT(0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_bool_value), + bad_bool_value)); + + gpr_cmdline_destroy(cl); +} + +static void test_badargs4(void) { + gpr_cmdline *cl; + + char *str = NULL; + int x = 0; + int flag = 2; + + char *bad_bool_value[] = {(char *)__FILE__, "--no-str"}; + + LOG_TEST(); + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_set_survive_failure(cl); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, + NULL); + + GPR_ASSERT(0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_bool_value), + bad_bool_value)); + + gpr_cmdline_destroy(cl); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_simple_int(); @@ -312,6 +484,13 @@ int main(int argc, char **argv) { test_flag_val_true(); test_flag_val_false(); test_many(); + test_extra(); + test_extra_dashdash(); test_usage(); + test_help(); + test_badargs1(); + test_badargs2(); + test_badargs3(); + test_badargs4(); return 0; } diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index 0d29bea555..fd57dd02f9 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -31,12 +31,13 @@ * */ -#include <grpc/grpc.h> +#include <string.h> -#include "test/core/end2end/cq_verifier.h" -#include "test/core/util/test_config.h" +#include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include "test/core/end2end/cq_verifier.h" +#include "test/core/util/test_config.h" static void *tag(gpr_intptr x) { return (void *)x; } @@ -47,21 +48,25 @@ int main(int argc, char **argv) { cq_verifier *cqv; grpc_op ops[6]; grpc_op *op; + grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_status_code status; grpc_call_error error; char *details = NULL; size_t details_capacity = 0; + char *peer; grpc_test_init(argc, argv); grpc_init(); + grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); chan = grpc_lame_client_channel_create( "lampoon:national", GRPC_STATUS_UNKNOWN, "Rpc sent on a lame channel."); GPR_ASSERT(chan); cq = grpc_completion_queue_create(NULL); + call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/Foo", "anywhere", GRPC_TIMEOUT_SECONDS_TO_DEADLINE(100), NULL); @@ -74,6 +79,19 @@ int main(int argc, char **argv) { op->flags = 0; op->reserved = NULL; op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* the call should immediately fail */ + cq_expect_completion(cqv, tag(1), 0); + cq_verify(cqv); + + op = ops; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; @@ -82,18 +100,23 @@ int main(int argc, char **argv) { op->flags = 0; op->reserved = NULL; op++; - error = grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(1), NULL); + error = grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(2), NULL); GPR_ASSERT(GRPC_CALL_OK == error); /* the call should immediately fail */ - cq_expect_completion(cqv, tag(1), 1); + cq_expect_completion(cqv, tag(2), 1); cq_verify(cqv); + peer = grpc_call_get_peer(call); + GPR_ASSERT(strcmp(peer, "lampoon:national") == 0); + gpr_free(peer); + grpc_call_destroy(call); grpc_channel_destroy(chan); cq_verifier_destroy(cqv); grpc_completion_queue_destroy(cq); + grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); gpr_free(details); diff --git a/test/core/surface/server_chttp2_test.c b/test/core/surface/server_chttp2_test.c new file mode 100644 index 0000000000..ec7df6f0e3 --- /dev/null +++ b/test/core/surface/server_chttp2_test.c @@ -0,0 +1,49 @@ +/* + * + * 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 <grpc/grpc.h> +#include <grpc/support/log.h> +#include "test/core/util/test_config.h" + +void test_unparsable_target(void) { + int port = grpc_server_add_insecure_http2_port(NULL, "["); + GPR_ASSERT(port == 0); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_unparsable_target(); + grpc_shutdown(); + return 0; +} diff --git a/tools/codegen/core/gen_legal_metadata_characters.c b/tools/codegen/core/gen_legal_metadata_characters.c index 677fa5c155..c6658f46c6 100644 --- a/tools/codegen/core/gen_legal_metadata_characters.c +++ b/tools/codegen/core/gen_legal_metadata_characters.c @@ -72,7 +72,6 @@ int main(void) { clear(); for (i = 32; i <= 126; i++) { - if (i == ',') continue; legal(i); } dump(); diff --git a/tools/run_tests/interop_html_report.template b/tools/run_tests/interop_html_report.template index 1ba2e6cfc2..c01bdf7a77 100644 --- a/tools/run_tests/interop_html_report.template +++ b/tools/run_tests/interop_html_report.template @@ -40,6 +40,26 @@ % endif </%def> +<%def name="fill_one_http2_test_result(shortname, resultset)"> + ## keep this mostly in sync with the template above + % if shortname in resultset: + ## Because interop tests does not have runs_per_test flag, each test is + ## run once. So there should only be one element for each result. + <% result = resultset[shortname][0] %> + <td bgcolor="white"> + <div style="width:95%; border: 1px solid black; position: relative; padding: 3px;"> + <span style="position: absolute; left: 45%;">${int(result.http2results['percent'] * 100)}%</span> + <div style="height: 20px; + background-color: hsl(${result.http2results['percent'] * 120}, 100%, 50%); + width: ${result.http2results['percent'] * 100}%;" + title="${result.http2results['failed_cases'] | h}"></div> + </div> + </td> + % else: + <td bgcolor="magenta">Not implemented</td> + % endif +</%def> + % if num_failures > 1: <p><h2><font color="red">${num_failures} tests failed!</font></h2></p> % elif num_failures: @@ -95,11 +115,11 @@ shortname = 'cloud_to_cloud:http2:%s_server:%s' % ( server_lang, test_case) %> - ${fill_one_test_result(shortname, resultset)} + ${fill_one_http2_test_result(shortname, resultset)} % endfor % if cloud_to_prod: <% shortname = 'cloud_to_prod:http2:%s' % test_case %> - ${fill_one_test_result(shortname, resultset)} + ${fill_one_http2_test_result(shortname, resultset)} % endif </tr> % endfor diff --git a/tools/run_tests/report_utils.py b/tools/run_tests/report_utils.py index 12b1972f1a..35f2069bee 100644 --- a/tools/run_tests/report_utils.py +++ b/tools/run_tests/report_utils.py @@ -32,6 +32,7 @@ try: from mako.runtime import Context from mako.template import Template + from mako import exceptions except (ImportError): pass # Mako not installed but it is ok. import os @@ -103,9 +104,15 @@ def render_interop_html_report( 'num_failures': num_failures, 'cloud_to_prod': cloud_to_prod, 'http2_interop': http2_interop} + html_report_out_dir = 'reports' if not os.path.exists(html_report_out_dir): os.mkdir(html_report_out_dir) html_file_path = os.path.join(html_report_out_dir, 'index.html') - with open(html_file_path, 'w') as output_file: - mytemplate.render_context(Context(output_file, **args)) + try: + with open(html_file_path, 'w') as output_file: + mytemplate.render_context(Context(output_file, **args)) + except: + print(exceptions.text_error_template().render()) + raise + diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 37b631bd0d..7a09feb70d 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -31,17 +31,24 @@ """Run interop (cross-language) tests in parallel.""" import argparse +import atexit import dockerjob import itertools import jobset +import json import multiprocessing import os +import re import report_utils +import subprocess import sys import tempfile import time import uuid +# Docker doesn't clean up after itself, so we do it on exit. +atexit.register(lambda: subprocess.call(['stty', 'echo'])) + ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..')) os.chdir(ROOT) @@ -52,6 +59,11 @@ _DEFAULT_SERVER_PORT=8080 # supported by C core SslCredentials instead. _SSL_CERT_ENV = { 'SSL_CERT_FILE':'/usr/local/share/grpc/roots.pem' } +_SKIP_COMPRESSION = ['large_compressed_unary', + 'server_compressed_streaming'] + +_SKIP_ADVANCED = ['custom_metadata', 'status_code_and_message', + 'unimplemented_method'] class CXXLanguage: @@ -73,7 +85,10 @@ class CXXLanguage: return {} def unimplemented_test_cases(self): - return [] + return _SKIP_ADVANCED + _SKIP_COMPRESSION + + def unimplemented_test_cases_server(self): + return _SKIP_ADVANCED + _SKIP_COMPRESSION def __str__(self): return 'c++' @@ -99,7 +114,11 @@ class CSharpLanguage: return {} def unimplemented_test_cases(self): - return [] + # TODO: status_code_and_message doesn't work against node_server + return _SKIP_COMPRESSION + ['status_code_and_message'] + + def unimplemented_test_cases_server(self): + return _SKIP_COMPRESSION def __str__(self): return 'csharp' @@ -125,7 +144,10 @@ class JavaLanguage: return {} def unimplemented_test_cases(self): - return [] + return _SKIP_ADVANCED + _SKIP_COMPRESSION + + def unimplemented_test_cases_server(self): + return _SKIP_ADVANCED + _SKIP_COMPRESSION def __str__(self): return 'java' @@ -152,7 +174,10 @@ class GoLanguage: return {} def unimplemented_test_cases(self): - return [] + return _SKIP_ADVANCED + _SKIP_COMPRESSION + + def unimplemented_test_cases_server(self): + return _SKIP_ADVANCED + _SKIP_COMPRESSION def __str__(self): return 'go' @@ -180,6 +205,9 @@ class Http2Client: def unimplemented_test_cases(self): return _TEST_CASES + def unimplemented_test_cases_server(self): + return [] + def __str__(self): return 'http2' @@ -203,7 +231,10 @@ class NodeLanguage: return {} def unimplemented_test_cases(self): - return [] + return _SKIP_COMPRESSION + + def unimplemented_test_cases_server(self): + return _SKIP_COMPRESSION def __str__(self): return 'node' @@ -225,6 +256,9 @@ class PHPLanguage: return {} def unimplemented_test_cases(self): + return _SKIP_ADVANCED + _SKIP_COMPRESSION + + def unimplemented_test_cases_server(self): return [] def __str__(self): @@ -251,7 +285,10 @@ class RubyLanguage: return {} def unimplemented_test_cases(self): - return [] + return _SKIP_ADVANCED + _SKIP_COMPRESSION + + def unimplemented_test_cases_server(self): + return _SKIP_ADVANCED + _SKIP_COMPRESSION def __str__(self): return 'ruby' @@ -289,7 +326,11 @@ class PythonLanguage: return {'LD_LIBRARY_PATH': '{}/libs/opt'.format(DOCKER_WORKDIR_ROOT)} def unimplemented_test_cases(self): - return ['jwt_token_creds', 'per_rpc_creds'] + return _SKIP_ADVANCED + _SKIP_COMPRESSION + ['jwt_token_creds', + 'per_rpc_creds'] + + def unimplemented_test_cases_server(self): + return _SKIP_ADVANCED + _SKIP_COMPRESSION def __str__(self): return 'python' @@ -312,7 +353,9 @@ _SERVERS = ['c++', 'node', 'csharp', 'java', 'go', 'ruby', 'python'] _TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong', 'empty_stream', 'client_streaming', 'server_streaming', 'cancel_after_begin', 'cancel_after_first_response', - 'timeout_on_sleeping_server'] + 'timeout_on_sleeping_server', 'custom_metadata', + 'status_code_and_message', 'unimplemented_method', + 'large_compressed_unary', 'server_compressed_streaming'] _AUTH_TEST_CASES = ['compute_engine_creds', 'jwt_token_creds', 'oauth2_auth_token', 'per_rpc_creds'] @@ -513,6 +556,33 @@ def build_interop_image_jobspec(language, tag=None): return build_job +def aggregate_http2_results(stdout): + match = re.search(r'\{"cases[^\]]*\]\}', stdout) + if not match: + return None + + results = json.loads(match.group(0)) + skipped = 0 + passed = 0 + failed = 0 + failed_cases = [] + for case in results['cases']: + if case.get('skipped', False): + skipped += 1 + else: + if case.get('passed', False): + passed += 1 + else: + failed += 1 + failed_cases.append(case.get('name', "NONAME")) + return { + 'passed': passed, + 'failed': failed, + 'skipped': skipped, + 'failed_cases': ', '.join(failed_cases), + 'percent': 1.0 * passed / (passed + failed) + } + argp = argparse.ArgumentParser(description='Run interop tests.') argp.add_argument('-l', '--language', choices=['all'] + sorted(_LANGUAGES), @@ -635,13 +705,12 @@ try: for language in languages: for test_case in _TEST_CASES: if not test_case in language.unimplemented_test_cases(): - test_job = cloud_to_prod_jobspec(language, test_case, - docker_image=docker_images.get(str(language))) - jobs.append(test_job) + if not test_case in _SKIP_ADVANCED + _SKIP_COMPRESSION: + test_job = cloud_to_prod_jobspec(language, test_case, + docker_image=docker_images.get(str(language))) + jobs.append(test_job) - # TODO(carl-mastrangelo): Currently prod TLS terminators aren't spec compliant. Reenable - # this once a better solution is in place. - if args.http2_interop and False: + if args.http2_interop: for test_case in _HTTP2_TEST_CASES: test_job = cloud_to_prod_jobspec(http2Interop, test_case, docker_image=docker_images.get(str(http2Interop))) @@ -664,16 +733,21 @@ try: for server_name, server_address in server_addresses.iteritems(): (server_host, server_port) = server_address + server_language = _LANGUAGES.get(server_name, None) + skip_server = [] # test cases unimplemented by server + if server_language: + skip_server = server_language.unimplemented_test_cases_server() for language in languages: for test_case in _TEST_CASES: if not test_case in language.unimplemented_test_cases(): - test_job = cloud_to_cloud_jobspec(language, - test_case, - server_name, - server_host, - server_port, - docker_image=docker_images.get(str(language))) - jobs.append(test_job) + if not test_case in skip_server: + test_job = cloud_to_cloud_jobspec(language, + test_case, + server_name, + server_host, + server_port, + docker_image=docker_images.get(str(language))) + jobs.append(test_job) if args.http2_interop: for test_case in _HTTP2_TEST_CASES: @@ -703,6 +777,10 @@ try: report_utils.render_junit_xml_report(resultset, 'report.xml') + for name, job in resultset.iteritems(): + if "http2" in name: + job[0].http2results = aggregate_http2_results(job[0].message) + report_utils.render_interop_html_report( set([str(l) for l in languages]), servers, _TEST_CASES, _AUTH_TEST_CASES, _HTTP2_TEST_CASES, resultset, num_failures, diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index e3df912480..006f4bcdf1 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -152,7 +152,10 @@ class CLanguage(object): else: binary = 'bins/%s/%s' % (config.build_config, target['name']) if os.path.isfile(binary): - out.append(config.job_spec([binary], [binary])) + out.append(config.job_spec([binary], [binary], + environ={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH': + os.path.abspath(os.path.dirname( + sys.argv[0]) + '/../../src/core/tsi/test_creds/ca.pem')})) elif args.regex == '.*' or platform_string() == 'windows': print '\nWARNING: binary not found, skipping', binary return sorted(out) @@ -192,6 +195,7 @@ class CLanguage(object): def __str__(self): return self.make_target + class NodeLanguage(object): def test_specs(self, config, args): diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 3fa7ac794e..e39f325717 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -751,6 +751,20 @@ ], "headers": [], "language": "c", + "name": "httpscli_test", + "src": [ + "test/core/httpcli/httpscli_test.c" + ] + }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "language": "c", "name": "init_test", "src": [ "test/core/surface/init_test.c" @@ -939,6 +953,20 @@ "gpr", "gpr_test_util", "grpc", + "grpc_test_util" + ], + "headers": [], + "language": "c", + "name": "server_chttp2_test", + "src": [ + "test/core/surface/server_chttp2_test.c" + ] + }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", "grpc_test_util", "test_tcp_server" ], diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index 6500f4368b..0c5f6be090 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -853,6 +853,18 @@ }, { "ci_platforms": [ + "linux" + ], + "exclude_configs": [], + "flaky": false, + "language": "c", + "name": "httpscli_test", + "platforms": [ + "linux" + ] + }, + { + "ci_platforms": [ "linux", "mac", "posix", @@ -1077,6 +1089,24 @@ "exclude_configs": [], "flaky": false, "language": "c", + "name": "server_chttp2_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, + { + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "exclude_configs": [], + "flaky": false, + "language": "c", "name": "set_initial_connect_string_test", "platforms": [ "linux", diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index 18db031e96..ef3bc46775 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -1769,6 +1769,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "secure_endpoint_test", "vcx {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server_chttp2_test", "vcxproj\test\server_chttp2_test\server_chttp2_test.vcxproj", "{BF9F909B-8266-6AAC-A81B-05F8210AA8CA}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {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}") = "set_initial_connect_string_test", "vcxproj\test\set_initial_connect_string_test\set_initial_connect_string_test.vcxproj", "{4A48E5A5-2E69-ED6D-063C-C297180A54D0}" ProjectSection(myProperties) = preProject lib = "False" @@ -12625,6 +12636,22 @@ Global {A7747106-A6BC-62D4-2A21-04A4F0CC2683}.Release-DLL|Win32.Build.0 = Release|Win32 {A7747106-A6BC-62D4-2A21-04A4F0CC2683}.Release-DLL|x64.ActiveCfg = Release|x64 {A7747106-A6BC-62D4-2A21-04A4F0CC2683}.Release-DLL|x64.Build.0 = Release|x64 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug|Win32.ActiveCfg = Debug|Win32 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug|x64.ActiveCfg = Debug|x64 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Release|Win32.ActiveCfg = Release|Win32 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Release|x64.ActiveCfg = Release|x64 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug|Win32.Build.0 = Debug|Win32 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug|x64.Build.0 = Debug|x64 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Release|Win32.Build.0 = Release|Win32 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Release|x64.Build.0 = Release|x64 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Debug-DLL|x64.Build.0 = Debug|x64 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Release-DLL|Win32.Build.0 = Release|Win32 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Release-DLL|x64.ActiveCfg = Release|x64 + {BF9F909B-8266-6AAC-A81B-05F8210AA8CA}.Release-DLL|x64.Build.0 = Release|x64 {4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|Win32.ActiveCfg = Debug|Win32 {4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|x64.ActiveCfg = Debug|x64 {4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/test/server_chttp2_test/server_chttp2_test.vcxproj b/vsprojects/vcxproj/test/server_chttp2_test/server_chttp2_test.vcxproj new file mode 100644 index 0000000000..eea4c96834 --- /dev/null +++ b/vsprojects/vcxproj/test/server_chttp2_test/server_chttp2_test.vcxproj @@ -0,0 +1,184 @@ +<?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>{BF9F909B-8266-6AAC-A81B-05F8210AA8CA}</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="'$(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_chttp2_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_chttp2_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;_USE_32BIT_TIME_T;%(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;_USE_32BIT_TIME_T;%(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\surface\server_chttp2_test.c"> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj"> + <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project> + </ProjectReference> + <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj"> + <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</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_chttp2_test/server_chttp2_test.vcxproj.filters b/vsprojects/vcxproj/test/server_chttp2_test/server_chttp2_test.vcxproj.filters new file mode 100644 index 0000000000..cdc9c6b48c --- /dev/null +++ b/vsprojects/vcxproj/test/server_chttp2_test/server_chttp2_test.vcxproj.filters @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="..\..\..\..\test\core\surface\server_chttp2_test.c"> + <Filter>test\core\surface</Filter> + </ClCompile> + </ItemGroup> + + <ItemGroup> + <Filter Include="test"> + <UniqueIdentifier>{95a6b4b6-b1fb-3c20-945d-ec3dbde1b334}</UniqueIdentifier> + </Filter> + <Filter Include="test\core"> + <UniqueIdentifier>{c0e66b85-9758-a554-2a83-be1a4ee1e27e}</UniqueIdentifier> + </Filter> + <Filter Include="test\core\surface"> + <UniqueIdentifier>{621e8242-2bcf-70e0-9db0-2c27907e925c}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project> + |