Merge branch 'master' of github.com:grpc/grpc into codegen_lib
This commit is contained in:
commit
cd21266b5f
|
|
@ -45,9 +45,13 @@ In order to run most of the available tests, one would need to run:
|
|||
|
||||
`./tools/run_tests/run_tests.py`
|
||||
|
||||
If you want to run all the possible tests for any of the languages {c, c++, node, php, python}, do this:
|
||||
If you want to run tests for any of the languages {c, c++, csharp, node, objc, php, python, ruby}, do this:
|
||||
|
||||
`./tools/run_tests/run_tests.py -l <lang> -c all`
|
||||
`./tools/run_tests/run_tests.py -l <lang>`
|
||||
|
||||
To know about the list of available commands, do this:
|
||||
|
||||
`./tools/run_tests/run_tests.py -h`
|
||||
|
||||
## Adding or removing source code
|
||||
|
||||
|
|
|
|||
72
Makefile
72
Makefile
|
|
@ -849,6 +849,8 @@ chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
|
|||
chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test
|
||||
chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test
|
||||
compression_test: $(BINDIR)/$(CONFIG)/compression_test
|
||||
concurrent_connectivity_test: $(BINDIR)/$(CONFIG)/concurrent_connectivity_test
|
||||
dns_resolver_connectivity_test: $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test
|
||||
dns_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_test
|
||||
dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test
|
||||
endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
|
||||
|
|
@ -1160,6 +1162,8 @@ buildtests_c: privatelibs_c \
|
|||
$(BINDIR)/$(CONFIG)/chttp2_stream_map_test \
|
||||
$(BINDIR)/$(CONFIG)/chttp2_varint_test \
|
||||
$(BINDIR)/$(CONFIG)/compression_test \
|
||||
$(BINDIR)/$(CONFIG)/concurrent_connectivity_test \
|
||||
$(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test \
|
||||
$(BINDIR)/$(CONFIG)/dns_resolver_test \
|
||||
$(BINDIR)/$(CONFIG)/dualstack_socket_test \
|
||||
$(BINDIR)/$(CONFIG)/endpoint_pair_test \
|
||||
|
|
@ -1404,6 +1408,10 @@ test_c: buildtests_c
|
|||
$(Q) $(BINDIR)/$(CONFIG)/chttp2_varint_test || ( echo test chttp2_varint_test failed ; exit 1 )
|
||||
$(E) "[RUN] Testing compression_test"
|
||||
$(Q) $(BINDIR)/$(CONFIG)/compression_test || ( echo test compression_test failed ; exit 1 )
|
||||
$(E) "[RUN] Testing concurrent_connectivity_test"
|
||||
$(Q) $(BINDIR)/$(CONFIG)/concurrent_connectivity_test || ( echo test concurrent_connectivity_test failed ; exit 1 )
|
||||
$(E) "[RUN] Testing dns_resolver_connectivity_test"
|
||||
$(Q) $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test || ( echo test dns_resolver_connectivity_test failed ; exit 1 )
|
||||
$(E) "[RUN] Testing dns_resolver_test"
|
||||
$(Q) $(BINDIR)/$(CONFIG)/dns_resolver_test || ( echo test dns_resolver_test failed ; exit 1 )
|
||||
$(E) "[RUN] Testing dualstack_socket_test"
|
||||
|
|
@ -6090,6 +6098,70 @@ endif
|
|||
endif
|
||||
|
||||
|
||||
CONCURRENT_CONNECTIVITY_TEST_SRC = \
|
||||
test/core/surface/concurrent_connectivity_test.c \
|
||||
|
||||
CONCURRENT_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CONCURRENT_CONNECTIVITY_TEST_SRC))))
|
||||
ifeq ($(NO_SECURE),true)
|
||||
|
||||
# You can't build secure targets if you don't have OpenSSL.
|
||||
|
||||
$(BINDIR)/$(CONFIG)/concurrent_connectivity_test: openssl_dep_error
|
||||
|
||||
else
|
||||
|
||||
|
||||
|
||||
$(BINDIR)/$(CONFIG)/concurrent_connectivity_test: $(CONCURRENT_CONNECTIVITY_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) $(CONCURRENT_CONNECTIVITY_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)/concurrent_connectivity_test
|
||||
|
||||
endif
|
||||
|
||||
$(OBJDIR)/$(CONFIG)/test/core/surface/concurrent_connectivity_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
|
||||
|
||||
deps_concurrent_connectivity_test: $(CONCURRENT_CONNECTIVITY_TEST_OBJS:.o=.dep)
|
||||
|
||||
ifneq ($(NO_SECURE),true)
|
||||
ifneq ($(NO_DEPS),true)
|
||||
-include $(CONCURRENT_CONNECTIVITY_TEST_OBJS:.o=.dep)
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
DNS_RESOLVER_CONNECTIVITY_TEST_SRC = \
|
||||
test/core/client_config/resolvers/dns_resolver_connectivity_test.c \
|
||||
|
||||
DNS_RESOLVER_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DNS_RESOLVER_CONNECTIVITY_TEST_SRC))))
|
||||
ifeq ($(NO_SECURE),true)
|
||||
|
||||
# You can't build secure targets if you don't have OpenSSL.
|
||||
|
||||
$(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test: openssl_dep_error
|
||||
|
||||
else
|
||||
|
||||
|
||||
|
||||
$(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test: $(DNS_RESOLVER_CONNECTIVITY_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) $(DNS_RESOLVER_CONNECTIVITY_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)/dns_resolver_connectivity_test
|
||||
|
||||
endif
|
||||
|
||||
$(OBJDIR)/$(CONFIG)/test/core/client_config/resolvers/dns_resolver_connectivity_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
|
||||
|
||||
deps_dns_resolver_connectivity_test: $(DNS_RESOLVER_CONNECTIVITY_TEST_OBJS:.o=.dep)
|
||||
|
||||
ifneq ($(NO_SECURE),true)
|
||||
ifneq ($(NO_DEPS),true)
|
||||
-include $(DNS_RESOLVER_CONNECTIVITY_TEST_OBJS:.o=.dep)
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
DNS_RESOLVER_TEST_SRC = \
|
||||
test/core/client_config/resolvers/dns_resolver_test.c \
|
||||
|
||||
|
|
|
|||
21
build.yaml
21
build.yaml
|
|
@ -1076,6 +1076,27 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: concurrent_connectivity_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/surface/concurrent_connectivity_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: dns_resolver_connectivity_test
|
||||
cpu_cost: 0.1
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/client_config/resolvers/dns_resolver_connectivity_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: dns_resolver_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
|
|||
|
|
@ -2,13 +2,20 @@
|
|||
"name": "grpc/grpc",
|
||||
"type": "library",
|
||||
"description": "gRPC library for PHP",
|
||||
"version": "0.6.0",
|
||||
"version": "0.14.0",
|
||||
"keywords": ["rpc"],
|
||||
"homepage": "http://grpc.io",
|
||||
"license": "BSD-3-Clause",
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/stanley-cheung/Protobuf-PHP"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.5.0",
|
||||
"google/auth": "dev-master"
|
||||
"datto/protobuf-php": "dev-master",
|
||||
"google/auth": "v0.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
{
|
||||
"name": "grpc/grpc-demo",
|
||||
"description": "gRPC example for PHP",
|
||||
"minimum-stability": "dev",
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/stanley-cheung/Protobuf-PHP"
|
||||
}
|
||||
],
|
||||
"name": "grpc/grpc-demo",
|
||||
"description": "gRPC example for PHP",
|
||||
"minimum-stability": "dev",
|
||||
"require": {
|
||||
"php": ">=5.5.0",
|
||||
"datto/protobuf-php": "dev-master",
|
||||
"google/auth": "dev-master",
|
||||
"grpc/grpc": "dev-release-0_11"
|
||||
"grpc/grpc": "dev-release-0_13"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -36,7 +36,9 @@ require dirname(__FILE__) . '/vendor/autoload.php';
|
|||
require dirname(__FILE__) . '/helloworld.php';
|
||||
|
||||
function greet($name) {
|
||||
$client = new helloworld\GreeterClient('localhost:50051', []);
|
||||
$client = new helloworld\GreeterClient('localhost:50051', [
|
||||
'credentials' => Grpc\ChannelCredentials::createInsecure()
|
||||
]);
|
||||
$request = new helloworld\HelloRequest();
|
||||
$request->setName($name);
|
||||
list($reply, $status) = $client->SayHello($request)->wait();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -37,7 +37,9 @@ require dirname(__FILE__) . '/route_guide.php';
|
|||
|
||||
define('COORD_FACTOR', 1e7);
|
||||
|
||||
$client = new routeguide\RouteGuideClient('localhost:50051', []);
|
||||
$client = new routeguide\RouteGuideClient('localhost:50051', [
|
||||
'credentials' => Grpc\ChannelCredentials::createInsecure()
|
||||
]);
|
||||
|
||||
function printFeature($feature) {
|
||||
$name = $feature->getName();
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ class CompletionQueue : private GrpcLibraryCodegen {
|
|||
}
|
||||
|
||||
/// Performs a single polling pluck on \a tag.
|
||||
/// \warning Must not be mixed with calls to \a Next.
|
||||
void TryPluck(CompletionQueueTag* tag) {
|
||||
auto deadline = gpr_time_0(GPR_CLOCK_REALTIME);
|
||||
auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ class ServerContext {
|
|||
void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
|
||||
void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
|
||||
|
||||
// IsCancelled is always safe to call when using sync API
|
||||
// When using async API, it is only safe to call IsCancelled after
|
||||
// the AsyncNotifyWhenDone tag has been delivered
|
||||
bool IsCancelled() const;
|
||||
|
||||
// Cancel the Call from the server. This is a best-effort API and depending on
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@
|
|||
<contents>
|
||||
<dir baseinstalldir="/" name="/">
|
||||
<file baseinstalldir="/" name="config.m4" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/README.md" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/ext/grpc/CREDITS" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/ext/grpc/LICENSE" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/ext/grpc/README.md" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/ext/grpc/byte_buffer.c" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/ext/grpc/call.c" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/ext/grpc/call_credentials.c" role="src" />
|
||||
|
|
|
|||
8
setup.py
8
setup.py
|
|
@ -108,8 +108,13 @@ if "linux" in sys.platform or "darwin" in sys.platform:
|
|||
|
||||
def cython_extensions(package_names, module_names, extra_sources, include_dirs,
|
||||
libraries, define_macros, build_with_cython=False):
|
||||
# Set compiler directives linetrace argument only if we care about tracing;
|
||||
# this is due to Cython having different behavior between linetrace being
|
||||
# False and linetrace being unset. See issue #5689.
|
||||
cython_compiler_directives = {}
|
||||
if ENABLE_CYTHON_TRACING:
|
||||
define_macros = define_macros + [('CYTHON_TRACE_NOGIL', 1)]
|
||||
cython_compiler_directives['linetrace'] = True
|
||||
file_extension = 'pyx' if build_with_cython else 'c'
|
||||
module_files = [os.path.join(PYTHON_STEM,
|
||||
name.replace('.', '/') + '.' + file_extension)
|
||||
|
|
@ -129,7 +134,7 @@ def cython_extensions(package_names, module_names, extra_sources, include_dirs,
|
|||
return Cython.Build.cythonize(
|
||||
extensions,
|
||||
include_path=include_dirs,
|
||||
compiler_directives={'linetrace': bool(ENABLE_CYTHON_TRACING)})
|
||||
compiler_directives=cython_compiler_directives)
|
||||
else:
|
||||
return extensions
|
||||
|
||||
|
|
@ -154,6 +159,7 @@ INSTALL_REQUIRES = (
|
|||
|
||||
SETUP_REQUIRES = (
|
||||
'sphinx>=1.3',
|
||||
'sphinx_rtd_theme>=0.1.8'
|
||||
) + INSTALL_REQUIRES
|
||||
|
||||
COMMAND_CLASS = {
|
||||
|
|
|
|||
|
|
@ -165,7 +165,6 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
channel_data *chand = arg;
|
||||
grpc_lb_policy *lb_policy = NULL;
|
||||
grpc_lb_policy *old_lb_policy;
|
||||
grpc_resolver *old_resolver;
|
||||
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
|
||||
int exit_idle = 0;
|
||||
|
||||
|
|
@ -201,28 +200,25 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
}
|
||||
|
||||
if (iomgr_success && chand->resolver) {
|
||||
grpc_resolver *resolver = chand->resolver;
|
||||
GRPC_RESOLVER_REF(resolver, "channel-next");
|
||||
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
|
||||
"new_lb+resolver");
|
||||
if (lb_policy != NULL) {
|
||||
watch_lb_policy(exec_ctx, chand, lb_policy, state);
|
||||
}
|
||||
gpr_mu_unlock(&chand->mu_config);
|
||||
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
|
||||
grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
|
||||
grpc_resolver_next(exec_ctx, chand->resolver,
|
||||
&chand->incoming_configuration,
|
||||
&chand->on_config_changed);
|
||||
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel-next");
|
||||
gpr_mu_unlock(&chand->mu_config);
|
||||
} else {
|
||||
old_resolver = chand->resolver;
|
||||
chand->resolver = NULL;
|
||||
if (chand->resolver != NULL) {
|
||||
grpc_resolver_shutdown(exec_ctx, chand->resolver);
|
||||
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
|
||||
chand->resolver = NULL;
|
||||
}
|
||||
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
|
||||
GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
|
||||
gpr_mu_unlock(&chand->mu_config);
|
||||
if (old_resolver != NULL) {
|
||||
grpc_resolver_shutdown(exec_ctx, old_resolver);
|
||||
GRPC_RESOLVER_UNREF(exec_ctx, old_resolver, "channel");
|
||||
}
|
||||
}
|
||||
|
||||
if (exit_idle) {
|
||||
|
|
@ -247,7 +243,6 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|||
grpc_channel_element *elem,
|
||||
grpc_transport_op *op) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
grpc_resolver *destroy_resolver = NULL;
|
||||
|
||||
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
|
||||
|
||||
|
|
@ -279,7 +274,8 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|||
if (op->disconnect && chand->resolver != NULL) {
|
||||
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
|
||||
GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
|
||||
destroy_resolver = chand->resolver;
|
||||
grpc_resolver_shutdown(exec_ctx, chand->resolver);
|
||||
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
|
||||
chand->resolver = NULL;
|
||||
if (chand->lb_policy != NULL) {
|
||||
grpc_pollset_set_del_pollset_set(exec_ctx,
|
||||
|
|
@ -290,11 +286,6 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|||
}
|
||||
}
|
||||
gpr_mu_unlock(&chand->mu_config);
|
||||
|
||||
if (destroy_resolver) {
|
||||
grpc_resolver_shutdown(exec_ctx, destroy_resolver);
|
||||
GRPC_RESOLVER_UNREF(exec_ctx, destroy_resolver, "channel");
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -174,17 +174,15 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
|
|||
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
||||
if (holder->connected_subchannel == NULL) {
|
||||
fail_locked(exec_ctx, holder);
|
||||
} else if (1 == gpr_atm_acq_load(&holder->subchannel_call)) {
|
||||
/* already cancelled before subchannel became ready */
|
||||
fail_locked(exec_ctx, holder);
|
||||
} else {
|
||||
if (!gpr_atm_rel_cas(
|
||||
&holder->subchannel_call, 0,
|
||||
(gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
|
||||
exec_ctx, holder->connected_subchannel, holder->pollset))) {
|
||||
GPR_ASSERT(gpr_atm_acq_load(&holder->subchannel_call) == 1);
|
||||
/* if this cas fails, the call was cancelled before the pick completed */
|
||||
fail_locked(exec_ctx, holder);
|
||||
} else {
|
||||
retry_waiting_locked(exec_ctx, holder);
|
||||
}
|
||||
gpr_atm_rel_store(
|
||||
&holder->subchannel_call,
|
||||
(gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
|
||||
exec_ctx, holder->connected_subchannel, holder->pollset));
|
||||
retry_waiting_locked(exec_ctx, holder);
|
||||
}
|
||||
gpr_mu_unlock(&holder->mu);
|
||||
GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -53,7 +53,9 @@ void grpc_client_config_ref(grpc_client_config *c) { gpr_ref(&c->refs); }
|
|||
|
||||
void grpc_client_config_unref(grpc_exec_ctx *exec_ctx, grpc_client_config *c) {
|
||||
if (gpr_unref(&c->refs)) {
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "client_config");
|
||||
if (c->lb_policy != NULL) {
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "client_config");
|
||||
}
|
||||
gpr_free(c);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -387,8 +387,8 @@ static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
|
|||
|
||||
static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory,
|
||||
grpc_lb_policy_args *args) {
|
||||
if (args->num_subchannels == 0) return NULL;
|
||||
pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
|
||||
GPR_ASSERT(args->num_subchannels > 0);
|
||||
memset(p, 0, sizeof(*p));
|
||||
grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
|
||||
p->subchannels =
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "src/core/client_config/lb_policy_registry.h"
|
||||
#include "src/core/iomgr/resolve_address.h"
|
||||
#include "src/core/iomgr/timer.h"
|
||||
#include "src/core/support/string.h"
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -71,6 +72,9 @@ typedef struct {
|
|||
grpc_client_config **target_config;
|
||||
/** current (fully resolved) config */
|
||||
grpc_client_config *resolved_config;
|
||||
/** retry timer */
|
||||
bool have_retry_timer;
|
||||
grpc_timer retry_timer;
|
||||
} dns_resolver;
|
||||
|
||||
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
|
||||
|
|
@ -91,6 +95,9 @@ static const grpc_resolver_vtable dns_resolver_vtable = {
|
|||
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
|
||||
dns_resolver *r = (dns_resolver *)resolver;
|
||||
gpr_mu_lock(&r->mu);
|
||||
if (r->have_retry_timer) {
|
||||
grpc_timer_cancel(exec_ctx, &r->retry_timer);
|
||||
}
|
||||
if (r->next_completion != NULL) {
|
||||
*r->target_config = NULL;
|
||||
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
|
||||
|
|
@ -125,6 +132,22 @@ static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
|
|||
gpr_mu_unlock(&r->mu);
|
||||
}
|
||||
|
||||
static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
|
||||
bool success) {
|
||||
dns_resolver *r = arg;
|
||||
|
||||
gpr_mu_lock(&r->mu);
|
||||
r->have_retry_timer = false;
|
||||
if (success) {
|
||||
if (!r->resolving) {
|
||||
dns_start_resolving_locked(r);
|
||||
}
|
||||
}
|
||||
gpr_mu_unlock(&r->mu);
|
||||
|
||||
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
|
||||
}
|
||||
|
||||
static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
|
||||
grpc_resolved_addresses *addresses) {
|
||||
dns_resolver *r = arg;
|
||||
|
|
@ -133,29 +156,47 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
grpc_subchannel_args args;
|
||||
grpc_lb_policy *lb_policy;
|
||||
size_t i;
|
||||
if (addresses) {
|
||||
gpr_mu_lock(&r->mu);
|
||||
GPR_ASSERT(r->resolving);
|
||||
r->resolving = 0;
|
||||
if (addresses != NULL) {
|
||||
grpc_lb_policy_args lb_policy_args;
|
||||
config = grpc_client_config_create();
|
||||
subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
|
||||
size_t naddrs = 0;
|
||||
for (i = 0; i < addresses->naddrs; i++) {
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
|
||||
args.addr_len = (size_t)addresses->addrs[i].len;
|
||||
subchannels[i] = grpc_subchannel_factory_create_subchannel(
|
||||
grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel(
|
||||
exec_ctx, r->subchannel_factory, &args);
|
||||
if (subchannel != NULL) {
|
||||
subchannels[naddrs++] = subchannel;
|
||||
}
|
||||
}
|
||||
memset(&lb_policy_args, 0, sizeof(lb_policy_args));
|
||||
lb_policy_args.subchannels = subchannels;
|
||||
lb_policy_args.num_subchannels = addresses->naddrs;
|
||||
lb_policy_args.num_subchannels = naddrs;
|
||||
lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
|
||||
grpc_client_config_set_lb_policy(config, lb_policy);
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
|
||||
if (lb_policy != NULL) {
|
||||
grpc_client_config_set_lb_policy(config, lb_policy);
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
|
||||
}
|
||||
grpc_resolved_addresses_destroy(addresses);
|
||||
gpr_free(subchannels);
|
||||
} else {
|
||||
int retry_seconds = 15;
|
||||
gpr_log(GPR_DEBUG, "dns resolution failed: retrying in %d seconds",
|
||||
retry_seconds);
|
||||
GPR_ASSERT(!r->have_retry_timer);
|
||||
r->have_retry_timer = true;
|
||||
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
|
||||
GRPC_RESOLVER_REF(&r->base, "retry-timer");
|
||||
grpc_timer_init(
|
||||
exec_ctx, &r->retry_timer,
|
||||
gpr_time_add(now, gpr_time_from_seconds(retry_seconds, GPR_TIMESPAN)),
|
||||
dns_on_retry_timer, r, now);
|
||||
}
|
||||
gpr_mu_lock(&r->mu);
|
||||
GPR_ASSERT(r->resolving);
|
||||
r->resolving = 0;
|
||||
if (r->resolved_config) {
|
||||
grpc_client_config_unref(exec_ctx, r->resolved_config);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -505,7 +505,8 @@ void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
|
|||
elem->filter->start_transport_op(exec_ctx, elem, &op);
|
||||
}
|
||||
|
||||
static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
|
||||
static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel *c) {
|
||||
size_t channel_stack_size;
|
||||
grpc_connected_subchannel *con;
|
||||
grpc_channel_stack *stk;
|
||||
|
|
@ -541,8 +542,6 @@ static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
|
|||
grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed,
|
||||
sw_subchannel);
|
||||
|
||||
gpr_mu_lock(&c->mu);
|
||||
|
||||
if (c->disconnected) {
|
||||
gpr_mu_unlock(&c->mu);
|
||||
gpr_free(sw_subchannel);
|
||||
|
|
@ -575,7 +574,6 @@ static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
|
|||
grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
|
||||
"connected");
|
||||
|
||||
gpr_mu_unlock(&c->mu);
|
||||
gpr_free((void *)filters);
|
||||
}
|
||||
|
||||
|
|
@ -644,21 +642,23 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
bool iomgr_success) {
|
||||
grpc_subchannel *c = arg;
|
||||
|
||||
GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
|
||||
gpr_mu_lock(&c->mu);
|
||||
if (c->connecting_result.transport != NULL) {
|
||||
publish_transport(exec_ctx, c);
|
||||
publish_transport_locked(exec_ctx, c);
|
||||
} else if (c->disconnected) {
|
||||
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
|
||||
} else {
|
||||
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
|
||||
gpr_mu_lock(&c->mu);
|
||||
GPR_ASSERT(!c->have_alarm);
|
||||
c->have_alarm = 1;
|
||||
grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
|
||||
GRPC_CHANNEL_TRANSIENT_FAILURE,
|
||||
"connect_failed");
|
||||
grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
|
||||
gpr_mu_unlock(&c->mu);
|
||||
}
|
||||
gpr_mu_unlock(&c->mu);
|
||||
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
|
||||
}
|
||||
|
||||
static gpr_timespec compute_connect_deadline(grpc_subchannel *c) {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ static DWORD deadline_to_millis_timeout(gpr_timespec deadline,
|
|||
timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
|
||||
}
|
||||
|
||||
void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) {
|
||||
grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
|
||||
gpr_timespec deadline) {
|
||||
BOOL success;
|
||||
DWORD bytes = 0;
|
||||
DWORD flags = 0;
|
||||
|
|
@ -84,14 +85,14 @@ void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) {
|
|||
g_iocp, &bytes, &completion_key, &overlapped,
|
||||
deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type)));
|
||||
if (success == 0 && overlapped == NULL) {
|
||||
return;
|
||||
return GRPC_IOCP_WORK_TIMEOUT;
|
||||
}
|
||||
GPR_ASSERT(completion_key && overlapped);
|
||||
if (overlapped == &g_iocp_custom_overlap) {
|
||||
gpr_atm_full_fetch_add(&g_custom_events, -1);
|
||||
if (completion_key == (ULONG_PTR)&g_iocp_kick_token) {
|
||||
/* We were awoken from a kick. */
|
||||
return;
|
||||
return GRPC_IOCP_WORK_KICK;
|
||||
}
|
||||
gpr_log(GPR_ERROR, "Unknown custom completion key.");
|
||||
abort();
|
||||
|
|
@ -121,6 +122,7 @@ void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) {
|
|||
}
|
||||
gpr_mu_unlock(&socket->state_mu);
|
||||
grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
|
||||
return GRPC_IOCP_WORK_WORK;
|
||||
}
|
||||
|
||||
void grpc_iocp_init(void) {
|
||||
|
|
@ -140,10 +142,12 @@ void grpc_iocp_kick(void) {
|
|||
|
||||
void grpc_iocp_flush(void) {
|
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
||||
grpc_iocp_work_status work_status;
|
||||
|
||||
do {
|
||||
grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC));
|
||||
} while (grpc_exec_ctx_flush(&exec_ctx));
|
||||
work_status = grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC));
|
||||
} while (work_status == GRPC_IOCP_WORK_KICK ||
|
||||
grpc_exec_ctx_flush(&exec_ctx));
|
||||
}
|
||||
|
||||
void grpc_iocp_shutdown(void) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -38,7 +38,14 @@
|
|||
|
||||
#include "src/core/iomgr/socket_windows.h"
|
||||
|
||||
void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline);
|
||||
typedef enum {
|
||||
GRPC_IOCP_WORK_WORK,
|
||||
GRPC_IOCP_WORK_TIMEOUT,
|
||||
GRPC_IOCP_WORK_KICK
|
||||
} grpc_iocp_work_status;
|
||||
|
||||
grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
|
||||
gpr_timespec deadline);
|
||||
void grpc_iocp_init(void);
|
||||
void grpc_iocp_kick(void);
|
||||
void grpc_iocp_flush(void);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -66,7 +66,7 @@ void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses);
|
|||
|
||||
/* Resolve addr in a blocking fashion. Returns NULL on failure. On success,
|
||||
result must be freed with grpc_resolved_addresses_destroy. */
|
||||
grpc_resolved_addresses *grpc_blocking_resolve_address(
|
||||
const char *addr, const char *default_port);
|
||||
extern grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
|
||||
const char *name, const char *default_port);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H */
|
||||
|
|
|
|||
|
|
@ -34,18 +34,13 @@
|
|||
#include <grpc/support/port_platform.h>
|
||||
#ifdef GPR_POSIX_SOCKET
|
||||
|
||||
#include "src/core/iomgr/sockaddr.h"
|
||||
#include "src/core/iomgr/resolve_address.h"
|
||||
#include "src/core/iomgr/sockaddr.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "src/core/iomgr/executor.h"
|
||||
#include "src/core/iomgr/iomgr_internal.h"
|
||||
#include "src/core/iomgr/sockaddr_utils.h"
|
||||
#include "src/core/support/block_annotate.h"
|
||||
#include "src/core/support/string.h"
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/host_port.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
|
@ -53,6 +48,11 @@
|
|||
#include <grpc/support/thd.h>
|
||||
#include <grpc/support/time.h>
|
||||
#include <grpc/support/useful.h>
|
||||
#include "src/core/iomgr/executor.h"
|
||||
#include "src/core/iomgr/iomgr_internal.h"
|
||||
#include "src/core/iomgr/sockaddr_utils.h"
|
||||
#include "src/core/support/block_annotate.h"
|
||||
#include "src/core/support/string.h"
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
|
|
@ -62,7 +62,7 @@ typedef struct {
|
|||
void *arg;
|
||||
} request;
|
||||
|
||||
grpc_resolved_addresses *grpc_blocking_resolve_address(
|
||||
static grpc_resolved_addresses *blocking_resolve_address_impl(
|
||||
const char *name, const char *default_port) {
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result = NULL, *resp;
|
||||
|
|
@ -150,6 +150,9 @@ done:
|
|||
return addrs;
|
||||
}
|
||||
|
||||
grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
|
||||
const char *name, const char *default_port) = blocking_resolve_address_impl;
|
||||
|
||||
/* Callback to be passed to grpc_executor to asynch-ify
|
||||
* grpc_blocking_resolve_address */
|
||||
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
|
||||
|
|
|
|||
|
|
@ -34,17 +34,12 @@
|
|||
#include <grpc/support/port_platform.h>
|
||||
#ifdef GPR_WINSOCK_SOCKET
|
||||
|
||||
#include "src/core/iomgr/sockaddr.h"
|
||||
#include "src/core/iomgr/resolve_address.h"
|
||||
#include "src/core/iomgr/sockaddr.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "src/core/iomgr/executor.h"
|
||||
#include "src/core/iomgr/iomgr_internal.h"
|
||||
#include "src/core/iomgr/sockaddr_utils.h"
|
||||
#include "src/core/support/block_annotate.h"
|
||||
#include "src/core/support/string.h"
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/host_port.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
|
@ -52,6 +47,11 @@
|
|||
#include <grpc/support/string_util.h>
|
||||
#include <grpc/support/thd.h>
|
||||
#include <grpc/support/time.h>
|
||||
#include "src/core/iomgr/executor.h"
|
||||
#include "src/core/iomgr/iomgr_internal.h"
|
||||
#include "src/core/iomgr/sockaddr_utils.h"
|
||||
#include "src/core/support/block_annotate.h"
|
||||
#include "src/core/support/string.h"
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
|
|
@ -61,7 +61,7 @@ typedef struct {
|
|||
void *arg;
|
||||
} request;
|
||||
|
||||
grpc_resolved_addresses *grpc_blocking_resolve_address(
|
||||
static grpc_resolved_addresses *blocking_resolve_address_impl(
|
||||
const char *name, const char *default_port) {
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result = NULL, *resp;
|
||||
|
|
@ -133,6 +133,9 @@ done:
|
|||
return addrs;
|
||||
}
|
||||
|
||||
grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
|
||||
const char *name, const char *default_port) = blocking_resolve_address_impl;
|
||||
|
||||
/* Callback to be passed to grpc_executor to asynch-ify
|
||||
* grpc_blocking_resolve_address */
|
||||
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
|
||||
|
|
|
|||
|
|
@ -240,8 +240,7 @@ static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
|
|||
sp->shutting_down = 0;
|
||||
gpr_mu_lock(&sp->server->mu);
|
||||
GPR_ASSERT(sp->server->active_ports > 0);
|
||||
if (0 == --sp->server->active_ports &&
|
||||
sp->server->shutdown_complete != NULL) {
|
||||
if (0 == --sp->server->active_ports) {
|
||||
notify = 1;
|
||||
}
|
||||
gpr_mu_unlock(&sp->server->mu);
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@
|
|||
|
||||
#include "src/core/iomgr/timer.h"
|
||||
|
||||
#include "src/core/iomgr/timer_heap.h"
|
||||
#include "src/core/iomgr/time_averaged_stats.h"
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/sync.h>
|
||||
#include <grpc/support/useful.h>
|
||||
#include "src/core/iomgr/time_averaged_stats.h"
|
||||
#include "src/core/iomgr/timer_heap.h"
|
||||
|
||||
#define INVALID_HEAP_INDEX 0xffffffffu
|
||||
|
||||
|
|
@ -330,6 +330,18 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
|
|||
|
||||
gpr_mu_unlock(&g_mu);
|
||||
gpr_mu_unlock(&g_checker_mu);
|
||||
} else if (next != NULL) {
|
||||
/* TODO(ctiller): this forces calling code to do an short poll, and
|
||||
then retry the timer check (because this time through the timer list was
|
||||
contended).
|
||||
|
||||
We could reduce the cost here dramatically by keeping a count of how many
|
||||
currently active pollers got through the uncontended case above
|
||||
successfully, and waking up other pollers IFF that count drops to zero.
|
||||
|
||||
Once that count is in place, this entire else branch could disappear. */
|
||||
*next = gpr_time_min(
|
||||
*next, gpr_time_add(now, gpr_time_from_millis(1, GPR_TIMESPAN)));
|
||||
}
|
||||
|
||||
return (int)n;
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer);
|
|||
*next is never guaranteed to be updated on any given execution; however,
|
||||
with high probability at least one thread in the system will see an update
|
||||
at any time slice. */
|
||||
|
||||
bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
|
||||
gpr_timespec *next);
|
||||
void grpc_timer_list_init(gpr_timespec now);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
static void adjust_upwards(grpc_timer **first, uint32_t i, grpc_timer *t) {
|
||||
while (i > 0) {
|
||||
uint32_t parent = (uint32_t)(((int)i - 1) / 2);
|
||||
if (gpr_time_cmp(first[parent]->deadline, t->deadline) >= 0) break;
|
||||
if (gpr_time_cmp(first[parent]->deadline, t->deadline) <= 0) break;
|
||||
first[i] = first[parent];
|
||||
first[i]->heap_index = i;
|
||||
i = parent;
|
||||
|
|
@ -62,16 +62,14 @@ static void adjust_downwards(grpc_timer **first, uint32_t i, uint32_t length,
|
|||
grpc_timer *t) {
|
||||
for (;;) {
|
||||
uint32_t left_child = 1u + 2u * i;
|
||||
uint32_t right_child;
|
||||
uint32_t next_i;
|
||||
if (left_child >= length) break;
|
||||
right_child = left_child + 1;
|
||||
next_i = right_child < length &&
|
||||
gpr_time_cmp(first[left_child]->deadline,
|
||||
first[right_child]->deadline) < 0
|
||||
? right_child
|
||||
: left_child;
|
||||
if (gpr_time_cmp(t->deadline, first[next_i]->deadline) >= 0) break;
|
||||
uint32_t right_child = left_child + 1;
|
||||
uint32_t next_i = right_child < length &&
|
||||
gpr_time_cmp(first[left_child]->deadline,
|
||||
first[right_child]->deadline) > 0
|
||||
? right_child
|
||||
: left_child;
|
||||
if (gpr_time_cmp(t->deadline, first[next_i]->deadline) <= 0) break;
|
||||
first[i] = first[next_i];
|
||||
first[i]->heap_index = i;
|
||||
i = next_i;
|
||||
|
|
@ -95,7 +93,7 @@ static void maybe_shrink(grpc_timer_heap *heap) {
|
|||
static void note_changed_priority(grpc_timer_heap *heap, grpc_timer *timer) {
|
||||
uint32_t i = timer->heap_index;
|
||||
uint32_t parent = (uint32_t)(((int)i - 1) / 2);
|
||||
if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) < 0) {
|
||||
if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) > 0) {
|
||||
adjust_upwards(heap->timers, i, timer);
|
||||
} else {
|
||||
adjust_downwards(heap->timers, i, heap->timer_count, timer);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -87,4 +87,4 @@ void *gpr_malloc_aligned(size_t size, size_t alignment_log) {
|
|||
return (void *)ret;
|
||||
}
|
||||
|
||||
void gpr_free_aligned(void *ptr) { free(((void **)ptr)[-1]); }
|
||||
void gpr_free_aligned(void *ptr) { gpr_free(((void **)ptr)[-1]); }
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ struct grpc_completion_queue {
|
|||
#define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
|
||||
|
||||
static gpr_mu g_freelist_mu;
|
||||
grpc_completion_queue *g_freelist;
|
||||
static grpc_completion_queue *g_freelist;
|
||||
|
||||
static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
|
||||
bool success);
|
||||
|
|
|
|||
|
|
@ -851,9 +851,11 @@ static void perform_stream_op_locked(
|
|||
if (stream_global->write_closed) {
|
||||
grpc_chttp2_complete_closure_step(
|
||||
exec_ctx, &stream_global->send_message_finished, 0);
|
||||
} else if (stream_global->id != 0) {
|
||||
} else {
|
||||
stream_global->send_message = op->send_message;
|
||||
grpc_chttp2_become_writable(transport_global, stream_global);
|
||||
if (stream_global->id != 0) {
|
||||
grpc_chttp2_become_writable(transport_global, stream_global);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -33,9 +33,18 @@
|
|||
|
||||
#include "src/core/tsi/ssl_transport_security.h"
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
/* TODO(jboeuf): refactor inet_ntop into a portability header. */
|
||||
#ifdef GPR_WINSOCK_SOCKET
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/sync.h>
|
||||
#include <grpc/support/thd.h>
|
||||
|
|
@ -197,13 +206,16 @@ static void ssl_info_callback(const SSL *ssl, int where, int ret) {
|
|||
}
|
||||
|
||||
/* Returns 1 if name looks like an IP address, 0 otherwise.
|
||||
This is a very rough heuristic as it does not handle IPV6 or things like:
|
||||
0300.0250.00.01, 0xC0.0Xa8.0x0.0x1, 000030052000001, 0xc0.052000001 */
|
||||
This is a very rough heuristic, and only handles IPv6 in hexadecimal form. */
|
||||
static int looks_like_ip_address(const char *name) {
|
||||
size_t i;
|
||||
size_t dot_count = 0;
|
||||
size_t num_size = 0;
|
||||
for (i = 0; i < strlen(name); i++) {
|
||||
if (name[i] == ':') {
|
||||
/* IPv6 Address in hexadecimal form, : is not allowed in DNS names. */
|
||||
return 1;
|
||||
}
|
||||
if (name[i] >= '0' && name[i] <= '9') {
|
||||
if (num_size > 3) return 0;
|
||||
num_size++;
|
||||
|
|
@ -296,21 +308,44 @@ static tsi_result add_subject_alt_names_properties_to_peer(
|
|||
sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i));
|
||||
/* Filter out the non-dns entries names. */
|
||||
if (subject_alt_name->type == GEN_DNS) {
|
||||
unsigned char *dns_name = NULL;
|
||||
int dns_name_size =
|
||||
ASN1_STRING_to_UTF8(&dns_name, subject_alt_name->d.dNSName);
|
||||
if (dns_name_size < 0) {
|
||||
unsigned char *name = NULL;
|
||||
int name_size;
|
||||
name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName);
|
||||
if (name_size < 0) {
|
||||
gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
|
||||
result = TSI_INTERNAL_ERROR;
|
||||
break;
|
||||
}
|
||||
result = tsi_construct_string_peer_property(
|
||||
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
|
||||
(const char *)dns_name, (size_t)dns_name_size,
|
||||
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, (const char *)name,
|
||||
(size_t)name_size, &peer->properties[peer->property_count++]);
|
||||
OPENSSL_free(name);
|
||||
} else if (subject_alt_name->type == GEN_IPADD) {
|
||||
char ntop_buf[INET6_ADDRSTRLEN];
|
||||
int af;
|
||||
|
||||
if (subject_alt_name->d.iPAddress->length == 4) {
|
||||
af = AF_INET;
|
||||
} else if (subject_alt_name->d.iPAddress->length == 16) {
|
||||
af = AF_INET6;
|
||||
} else {
|
||||
gpr_log(GPR_ERROR, "SAN IP Address contained invalid IP");
|
||||
result = TSI_INTERNAL_ERROR;
|
||||
break;
|
||||
}
|
||||
const char *name = inet_ntop(af, subject_alt_name->d.iPAddress->data,
|
||||
ntop_buf, INET6_ADDRSTRLEN);
|
||||
if (name == NULL) {
|
||||
gpr_log(GPR_ERROR, "Could not get IP string from asn1 octet.");
|
||||
result = TSI_INTERNAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
result = tsi_construct_string_peer_property_from_cstring(
|
||||
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name,
|
||||
&peer->properties[peer->property_count++]);
|
||||
OPENSSL_free(dns_name);
|
||||
if (result != TSI_OK) break;
|
||||
}
|
||||
if (result != TSI_OK) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1436,9 +1471,7 @@ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
|
|||
size_t i = 0;
|
||||
size_t san_count = 0;
|
||||
const tsi_peer_property *cn_property = NULL;
|
||||
|
||||
/* For now reject what looks like an IP address. */
|
||||
if (looks_like_ip_address(name)) return 0;
|
||||
int like_ip = looks_like_ip_address(name);
|
||||
|
||||
/* Check the SAN first. */
|
||||
for (i = 0; i < peer->property_count; i++) {
|
||||
|
|
@ -1447,8 +1480,15 @@ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
|
|||
if (strcmp(property->name,
|
||||
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
|
||||
san_count++;
|
||||
if (does_entry_match_name(property->value.data, property->value.length,
|
||||
name)) {
|
||||
|
||||
if (!like_ip && does_entry_match_name(property->value.data,
|
||||
property->value.length, name)) {
|
||||
return 1;
|
||||
} else if (like_ip &&
|
||||
strncmp(name, property->value.data, property->value.length) ==
|
||||
0 &&
|
||||
strlen(name) == property->value.length) {
|
||||
/* IP Addresses are exact matches only. */
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(property->name,
|
||||
|
|
@ -1457,8 +1497,8 @@ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
|
|||
}
|
||||
}
|
||||
|
||||
/* If there's no SAN, try the CN. */
|
||||
if (san_count == 0 && cn_property != NULL) {
|
||||
/* If there's no SAN, try the CN, but only if its not like an IP Address */
|
||||
if (san_count == 0 && cn_property != NULL && !like_ip) {
|
||||
if (does_entry_match_name(cn_property->value.data,
|
||||
cn_property->value.length, name)) {
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -162,8 +162,7 @@ void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self);
|
|||
Still TODO(jboeuf):
|
||||
- handle mixed case.
|
||||
- handle %encoded chars.
|
||||
- handle public suffix wildchar more strictly (e.g. *.co.uk)
|
||||
- handle IP addresses in SAN. */
|
||||
- handle public suffix wildchar more strictly (e.g. *.co.uk) */
|
||||
int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -6,3 +6,77 @@ This directory contains source code for C++ implementation of gRPC.
|
|||
#Status
|
||||
|
||||
Beta
|
||||
|
||||
#Pre-requisites
|
||||
|
||||
##Linux
|
||||
|
||||
```sh
|
||||
$ [sudo] apt-get install build-essential autoconf libtool
|
||||
```
|
||||
|
||||
##Mac OSX
|
||||
|
||||
For a Mac system, git is not available by default. You will first need to
|
||||
install Xcode from the Mac AppStore and then run the following command from a
|
||||
terminal:
|
||||
|
||||
```sh
|
||||
$ [sudo] xcode-select --install
|
||||
```
|
||||
|
||||
##Protoc
|
||||
|
||||
By default gRPC uses [protocol buffers](https://github.com/google/protobuf),
|
||||
you will need the `protoc` compiler to generate stub server and client code.
|
||||
|
||||
If you compile gRPC from source, as described below, this also installs the
|
||||
`protoc` compiler.
|
||||
|
||||
If it hasn't been installed, you can run the following commands to install it.
|
||||
|
||||
```sh
|
||||
$ cd grpc/third_party/protobuf
|
||||
$ sudo make install # 'make' should have been run by core grpc
|
||||
```
|
||||
|
||||
Alternatively, you can download `protoc` binaries from
|
||||
[the protocol buffers Github repository](https://github.com/google/protobuf/releases).
|
||||
|
||||
#Installation
|
||||
|
||||
Currently to install gRPC for C++, you need to build from source as described
|
||||
below.
|
||||
|
||||
#Build from Source
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/grpc/grpc.git
|
||||
$ cd grpc
|
||||
$ git submodule update --init
|
||||
$ make
|
||||
$ [sudo] make install
|
||||
```
|
||||
|
||||
#Documentation
|
||||
|
||||
You can find out how to build and run our simplest gRPC C++ example in our
|
||||
[C++ quick start](https://github.com/grpc/grpc/tree/{{ site.data.config.grpc_release_branch }}/examples/cpp).
|
||||
|
||||
For more detailed documentation on using gRPC in C++ , see our main
|
||||
documentation site at [grpc.io](http://grpc.io), specifically:
|
||||
|
||||
* [Overview](http://www.grpc.io/docs/): An introduction to gRPC with a simple
|
||||
Hello World example in all our supported languages, including C++.
|
||||
* [gRPC Basics - C++](http://www.grpc.io/docs/tutorials/basic/c.html):
|
||||
A tutorial that steps you through creating a simple gRPC C++ example
|
||||
application.
|
||||
* [Asynchronous Basics - C++](http://www.grpc.io/docs/tutorials/async/helloasync-cpp.html):
|
||||
A tutorial that shows you how to use gRPC C++'s asynchronous/non-blocking
|
||||
APIs.
|
||||
|
||||
|
||||
# Examples
|
||||
|
||||
Code examples for gRPC C++ live in this repository's
|
||||
[examples/cpp](https://github.com/grpc/grpc/tree/{{ site.data.config.grpc_release_branch }}/examples/cpp) directory.
|
||||
|
|
|
|||
|
|
@ -62,7 +62,11 @@ class ServerContext::CompletionOp GRPC_FINAL : public CallOpSetInterface {
|
|||
void FillOps(grpc_op* ops, size_t* nops) GRPC_OVERRIDE;
|
||||
bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE;
|
||||
|
||||
bool CheckCancelled(CompletionQueue* cq);
|
||||
bool CheckCancelled(CompletionQueue* cq) {
|
||||
cq->TryPluck(this);
|
||||
return CheckCancelledNoPluck();
|
||||
}
|
||||
bool CheckCancelledAsync() { return CheckCancelledNoPluck(); }
|
||||
|
||||
void set_tag(void* tag) {
|
||||
has_tag_ = true;
|
||||
|
|
@ -72,6 +76,11 @@ class ServerContext::CompletionOp GRPC_FINAL : public CallOpSetInterface {
|
|||
void Unref();
|
||||
|
||||
private:
|
||||
bool CheckCancelledNoPluck() {
|
||||
grpc::lock_guard<grpc::mutex> g(mu_);
|
||||
return finalized_ ? (cancelled_ != 0) : false;
|
||||
}
|
||||
|
||||
bool has_tag_;
|
||||
void* tag_;
|
||||
grpc::mutex mu_;
|
||||
|
|
@ -88,12 +97,6 @@ void ServerContext::CompletionOp::Unref() {
|
|||
}
|
||||
}
|
||||
|
||||
bool ServerContext::CompletionOp::CheckCancelled(CompletionQueue* cq) {
|
||||
cq->TryPluck(this);
|
||||
grpc::lock_guard<grpc::mutex> g(mu_);
|
||||
return finalized_ ? cancelled_ != 0 : false;
|
||||
}
|
||||
|
||||
void ServerContext::CompletionOp::FillOps(grpc_op* ops, size_t* nops) {
|
||||
ops->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
|
||||
ops->data.recv_close_on_server.cancelled = &cancelled_;
|
||||
|
|
@ -182,7 +185,14 @@ void ServerContext::TryCancel() const {
|
|||
}
|
||||
|
||||
bool ServerContext::IsCancelled() const {
|
||||
return completion_op_ && completion_op_->CheckCancelled(cq_);
|
||||
if (has_notify_when_done_tag_) {
|
||||
// when using async API, but the result is only valid
|
||||
// if the tag has already been delivered at the completion queue
|
||||
return completion_op_ && completion_op_->CheckCancelledAsync();
|
||||
} else {
|
||||
// when using sync API
|
||||
return completion_op_ && completion_op_->CheckCancelled(cq_);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerContext::set_compression_level(grpc_compression_level level) {
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ namespace Grpc.Core
|
|||
|
||||
private static string NormalizeKey(string key)
|
||||
{
|
||||
var normalized = GrpcPreconditions.CheckNotNull(key, "key").ToLower(CultureInfo.InvariantCulture);
|
||||
var normalized = GrpcPreconditions.CheckNotNull(key, "key").ToLowerInvariant();
|
||||
GrpcPreconditions.CheckArgument(ValidKeyRegex.IsMatch(normalized),
|
||||
"Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores and hyphens.");
|
||||
return normalized;
|
||||
|
|
|
|||
|
|
@ -149,6 +149,9 @@ function _readsDone(status) {
|
|||
if (!status) {
|
||||
status = {code: grpc.status.OK, details: 'OK'};
|
||||
}
|
||||
if (status.code !== grpc.status.OK) {
|
||||
this.call.cancelWithStatus(status.code, status.details);
|
||||
}
|
||||
this.finished = true;
|
||||
this.read_status = status;
|
||||
this._emitStatusIfDone();
|
||||
|
|
@ -408,7 +411,7 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
|
|||
}
|
||||
}
|
||||
if (status.code !== grpc.status.OK) {
|
||||
error = new Error(response.status.details);
|
||||
error = new Error(status.details);
|
||||
error.code = status.code;
|
||||
error.metadata = status.metadata;
|
||||
callback(error);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
#include <grpc/support/time.h>
|
||||
#import <RxLibrary/GRXConcurrentWriteable.h>
|
||||
|
||||
#import "private/GRPCConnectivityMonitor.h"
|
||||
#import "private/GRPCHost.h"
|
||||
#import "private/GRPCRequestHeaders.h"
|
||||
#import "private/GRPCWrappedCall.h"
|
||||
#import "private/NSData+GRPC.h"
|
||||
|
|
@ -71,8 +73,11 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
|
|||
@implementation GRPCCall {
|
||||
dispatch_queue_t _callQueue;
|
||||
|
||||
NSString *_host;
|
||||
NSString *_path;
|
||||
GRPCWrappedCall *_wrappedCall;
|
||||
dispatch_once_t _callAlreadyInvoked;
|
||||
GRPCConnectivityMonitor *_connectivityMonitor;
|
||||
|
||||
// The C gRPC library has less guarantees on the ordering of events than we
|
||||
// do. Particularly, in the face of errors, there's no ordering guarantee at
|
||||
|
|
@ -115,13 +120,11 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
|
|||
format:@"The requests writer can't be already started."];
|
||||
}
|
||||
if ((self = [super init])) {
|
||||
_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:host path:path];
|
||||
if (!_wrappedCall) {
|
||||
return nil;
|
||||
}
|
||||
_host = [host copy];
|
||||
_path = [path copy];
|
||||
|
||||
// Serial queue to invoke the non-reentrant methods of the grpc_call object.
|
||||
_callQueue = dispatch_queue_create("org.grpc.call", NULL);
|
||||
_callQueue = dispatch_queue_create("io.grpc.call", NULL);
|
||||
|
||||
_requestWriter = requestWriter;
|
||||
|
||||
|
|
@ -156,7 +159,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
|
|||
- (void)cancel {
|
||||
[self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
|
||||
code:GRPCErrorCodeCancelled
|
||||
userInfo:nil]];
|
||||
userInfo:@{NSLocalizedDescriptionKey: @"Canceled by app"}]];
|
||||
[self cancelCall];
|
||||
}
|
||||
|
||||
|
|
@ -354,8 +357,29 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
|
|||
_retainSelf = self;
|
||||
|
||||
_responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable];
|
||||
|
||||
_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path];
|
||||
NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?");
|
||||
|
||||
[self sendHeaders:_requestHeaders];
|
||||
[self invokeCall];
|
||||
// TODO(jcanizales): Extract this logic somewhere common.
|
||||
NSString *host = [NSURL URLWithString:[@"https://" stringByAppendingString:_host]].host;
|
||||
if (!host) {
|
||||
// TODO(jcanizales): Check this on init.
|
||||
[NSException raise:NSInvalidArgumentException format:@"host of %@ is nil", _host];
|
||||
}
|
||||
__weak typeof(self) weakSelf = self;
|
||||
_connectivityMonitor = [GRPCConnectivityMonitor monitorWithHost:host];
|
||||
[_connectivityMonitor handleLossWithHandler:^{
|
||||
typeof(self) strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
[strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
|
||||
code:GRPCErrorCodeUnavailable
|
||||
userInfo:@{NSLocalizedDescriptionKey: @"Connectivity lost."}]];
|
||||
[[GRPCHost hostWithAddress:strongSelf->_host] disconnect];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setState:(GRXWriterState)newState {
|
||||
|
|
@ -385,4 +409,5 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include <grpc/grpc.h>
|
||||
|
||||
@class GRPCCompletionQueue;
|
||||
struct grpc_channel_credentials;
|
||||
|
||||
|
||||
|
|
@ -80,4 +81,6 @@ struct grpc_channel_credentials;
|
|||
+ (nonnull GRPCChannel *)insecureChannelWithHost:(nonnull NSString *)host
|
||||
channelArgs:(nullable NSDictionary *)channelArgs;
|
||||
|
||||
- (nullable grpc_call *)unmanagedCallWithPath:(nonnull NSString *)path
|
||||
completionQueue:(nonnull GRPCCompletionQueue *)queue;
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/string_util.h>
|
||||
|
||||
#import "GRPCCompletionQueue.h"
|
||||
|
||||
/**
|
||||
* Returns @c grpc_channel_credentials from the specified @c path. If the file at the path could not
|
||||
* be read then NULL is returned. If NULL is returned, @c errorPtr may not be NULL if there are
|
||||
|
|
@ -205,4 +207,16 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
|
|||
channelArgs:channelArgs];
|
||||
}
|
||||
|
||||
- (grpc_call *)unmanagedCallWithPath:(NSString *)path
|
||||
completionQueue:(GRPCCompletionQueue *)queue {
|
||||
return grpc_channel_create_call(_unmanagedChannel,
|
||||
NULL, GRPC_PROPAGATE_DEFAULTS,
|
||||
queue.unmanagedQueue,
|
||||
path.UTF8String,
|
||||
// Get "host" from "host:port"
|
||||
// TODO(jcanizales): Use NSURLs throughout, to clarify these.
|
||||
[_host componentsSeparatedByString:@":"][0].UTF8String,
|
||||
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
typedef void(^GRPCQueueCompletionHandler)(bool success);
|
||||
|
||||
extern const int64_t kGRPCCompletionQueueDefaultTimeoutSecs;
|
||||
|
||||
/**
|
||||
* This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the
|
||||
* |unmanagedQueue| property of an instance of this class to |grpc_channel_create_call|. Then for
|
||||
|
|
@ -49,6 +51,11 @@ typedef void(^GRPCQueueCompletionHandler)(bool success);
|
|||
*/
|
||||
@interface GRPCCompletionQueue : NSObject
|
||||
@property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue;
|
||||
@property(nonatomic, readonly) int64_t timeoutSecs;
|
||||
|
||||
+ (instancetype)completionQueue;
|
||||
|
||||
- (instancetype)init;
|
||||
- (instancetype)initWithTimeout:(int64_t)timeoutSecs NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -35,15 +35,28 @@
|
|||
|
||||
#import <grpc/grpc.h>
|
||||
|
||||
|
||||
const int64_t kGRPCCompletionQueueDefaultTimeoutSecs = 60;
|
||||
|
||||
@implementation GRPCCompletionQueue
|
||||
|
||||
+ (instancetype)completionQueue {
|
||||
return [[self alloc] init];
|
||||
static GRPCCompletionQueue *singleton = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
singleton = [[self alloc] init];
|
||||
});
|
||||
return singleton;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
return [self initWithTimeout:kGRPCCompletionQueueDefaultTimeoutSecs];
|
||||
}
|
||||
|
||||
- (instancetype)initWithTimeout:(int64_t)timeoutSecs {
|
||||
if ((self = [super init])) {
|
||||
_unmanagedQueue = grpc_completion_queue_create(NULL);
|
||||
_timeoutSecs = timeoutSecs;
|
||||
|
||||
// This is for the following block to capture the pointer by value (instead
|
||||
// of retaining self and doing self->_unmanagedQueue). This is essential
|
||||
|
|
@ -61,22 +74,28 @@
|
|||
gDefaultConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
});
|
||||
dispatch_async(gDefaultConcurrentQueue, ^{
|
||||
// Using a non-infinite deadline to re-enter grpc_completion_queue_next()
|
||||
// alleviates https://github.com/grpc/grpc/issues/5593
|
||||
gpr_timespec deadline = (timeoutSecs < 0)
|
||||
? gpr_inf_future(GPR_CLOCK_REALTIME)
|
||||
: gpr_time_from_seconds(timeoutSecs, GPR_CLOCK_REALTIME);
|
||||
while (YES) {
|
||||
// The following call blocks until an event is available.
|
||||
grpc_event event = grpc_completion_queue_next(unmanagedQueue,
|
||||
gpr_inf_future(GPR_CLOCK_REALTIME),
|
||||
NULL);
|
||||
// The following call blocks until an event is available or the deadline elapses.
|
||||
grpc_event event = grpc_completion_queue_next(unmanagedQueue, deadline, NULL);
|
||||
GRPCQueueCompletionHandler handler;
|
||||
switch (event.type) {
|
||||
case GRPC_OP_COMPLETE:
|
||||
handler = (__bridge_transfer GRPCQueueCompletionHandler)event.tag;
|
||||
handler(event.success);
|
||||
break;
|
||||
case GRPC_QUEUE_TIMEOUT:
|
||||
// Nothing to do here
|
||||
break;
|
||||
case GRPC_QUEUE_SHUTDOWN:
|
||||
grpc_completion_queue_destroy(unmanagedQueue);
|
||||
return;
|
||||
default:
|
||||
[NSException raise:@"Unrecognized completion type" format:@""];
|
||||
[NSException raise:@"Unrecognized completion type" format:@"type=%d", event.type];
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
|
||||
@interface GRPCReachabilityFlags : NSObject
|
||||
|
||||
+ (nonnull instancetype)flagsWithFlags:(SCNetworkReachabilityFlags)flags;
|
||||
|
||||
/**
|
||||
* One accessor method to query each of the different flags. Example:
|
||||
|
||||
@property(nonatomic, readonly) BOOL isCell;
|
||||
|
||||
*/
|
||||
#define GRPC_XMACRO_ITEM(methodName, FlagName) \
|
||||
@property(nonatomic, readonly) BOOL methodName;
|
||||
|
||||
#include "GRPCReachabilityFlagNames.xmacro.h"
|
||||
#undef GRPC_XMACRO_ITEM
|
||||
|
||||
@property(nonatomic, readonly) BOOL isHostReachable;
|
||||
@end
|
||||
|
||||
|
||||
@interface GRPCConnectivityMonitor : NSObject
|
||||
|
||||
+ (nullable instancetype)monitorWithHost:(nonnull NSString *)hostName;
|
||||
|
||||
- (nonnull instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Queue on which callbacks will be dispatched. Default is the main queue. Set it before calling
|
||||
* handleLossWithHandler:.
|
||||
*/
|
||||
// TODO(jcanizales): Default to a serial background queue instead.
|
||||
@property(nonatomic, strong, null_resettable) dispatch_queue_t queue;
|
||||
|
||||
/**
|
||||
* Calls handler every time the connectivity to this instance's host is lost. If this instance is
|
||||
* released before that happens, the handler won't be called.
|
||||
* Only one handler is active at a time, so if this method is called again before the previous
|
||||
* handler has been called, it might never be called at all (or yes, if it has already been queued).
|
||||
*/
|
||||
- (void)handleLossWithHandler:(nonnull void (^)())handler;
|
||||
@end
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "GRPCConnectivityMonitor.h"
|
||||
|
||||
#pragma mark Flags
|
||||
|
||||
@implementation GRPCReachabilityFlags {
|
||||
SCNetworkReachabilityFlags _flags;
|
||||
}
|
||||
|
||||
+ (instancetype)flagsWithFlags:(SCNetworkReachabilityFlags)flags {
|
||||
return [[self alloc] initWithFlags:flags];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFlags:(SCNetworkReachabilityFlags)flags {
|
||||
if ((self = [super init])) {
|
||||
_flags = flags;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* One accessor method implementation per flag. Example:
|
||||
|
||||
- (BOOL)isCell { \
|
||||
return !!(_flags & kSCNetworkReachabilityFlagsIsWWAN); \
|
||||
}
|
||||
|
||||
*/
|
||||
#define GRPC_XMACRO_ITEM(methodName, FlagName) \
|
||||
- (BOOL)methodName { \
|
||||
return !!(_flags & kSCNetworkReachabilityFlags ## FlagName); \
|
||||
}
|
||||
#include "GRPCReachabilityFlagNames.xmacro.h"
|
||||
#undef GRPC_XMACRO_ITEM
|
||||
|
||||
- (BOOL)isHostReachable {
|
||||
// Note: connectionOnDemand means it'll be reachable only if using the CFSocketStream API or APIs
|
||||
// on top of it.
|
||||
// connectionRequired means we can't tell until a connection is attempted (e.g. for VPN on
|
||||
// demand).
|
||||
return self.reachable && !self.interventionRequired && !self.connectionOnDemand;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
NSMutableArray *activeOptions = [NSMutableArray arrayWithCapacity:9];
|
||||
|
||||
/*
|
||||
* For each flag, add its name to the array if it's ON. Example:
|
||||
|
||||
if (self.isCell) {
|
||||
[activeOptions addObject:@"isCell"];
|
||||
}
|
||||
|
||||
*/
|
||||
#define GRPC_XMACRO_ITEM(methodName, FlagName) \
|
||||
if (self.methodName) { \
|
||||
[activeOptions addObject:@#methodName]; \
|
||||
}
|
||||
#include "GRPCReachabilityFlagNames.xmacro.h"
|
||||
#undef GRPC_XMACRO_ITEM
|
||||
|
||||
return activeOptions.count == 0 ? @"(none)" : [activeOptions componentsJoinedByString:@", "];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
return [object isKindOfClass:[GRPCReachabilityFlags class]] &&
|
||||
_flags == ((GRPCReachabilityFlags *)object)->_flags;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return _flags;
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma mark Connectivity Monitor
|
||||
|
||||
// Assumes the third argument is a block that accepts a GRPCReachabilityFlags object, and passes the
|
||||
// received ones to it.
|
||||
static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target,
|
||||
SCNetworkReachabilityFlags flags,
|
||||
void *info) {
|
||||
#pragma unused (target)
|
||||
// This can be called many times with the same info. The info is retained by SCNetworkReachability
|
||||
// while this function is being executed.
|
||||
void (^handler)(GRPCReachabilityFlags *) = (__bridge void (^)(GRPCReachabilityFlags *))info;
|
||||
handler([[GRPCReachabilityFlags alloc] initWithFlags:flags]);
|
||||
}
|
||||
|
||||
@implementation GRPCConnectivityMonitor {
|
||||
SCNetworkReachabilityRef _reachabilityRef;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithReachability:(nullable SCNetworkReachabilityRef)reachability {
|
||||
if (!reachability) {
|
||||
return nil;
|
||||
}
|
||||
if ((self = [super init])) {
|
||||
_reachabilityRef = CFRetain(reachability);
|
||||
_queue = dispatch_get_main_queue();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (nullable instancetype)monitorWithHost:(nonnull NSString *)host {
|
||||
const char *hostName = host.UTF8String;
|
||||
if (!hostName) {
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"host.UTF8String returns NULL for %@", host];
|
||||
}
|
||||
SCNetworkReachabilityRef reachability =
|
||||
SCNetworkReachabilityCreateWithName(NULL, hostName);
|
||||
|
||||
GRPCConnectivityMonitor *returnValue = [[self alloc] initWithReachability:reachability];
|
||||
if (reachability) {
|
||||
CFRelease(reachability);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
- (void)handleLossWithHandler:(void (^)())handler {
|
||||
[self startListeningWithHandler:^(GRPCReachabilityFlags *flags) {
|
||||
if (!flags.isHostReachable) {
|
||||
handler();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)startListeningWithHandler:(void (^)(GRPCReachabilityFlags *))handler {
|
||||
// Copy to ensure the handler block is in the heap (and so can't be deallocated when this method
|
||||
// returns).
|
||||
void (^copiedHandler)(GRPCReachabilityFlags *) = [handler copy];
|
||||
SCNetworkReachabilityContext context = {
|
||||
.version = 0,
|
||||
.info = (__bridge void *)copiedHandler,
|
||||
.retain = CFRetain,
|
||||
.release = CFRelease,
|
||||
};
|
||||
// The following will retain context.info, and release it when the callback is set to NULL.
|
||||
SCNetworkReachabilitySetCallback(_reachabilityRef, PassFlagsToContextInfoBlock, &context);
|
||||
SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _queue);
|
||||
}
|
||||
|
||||
- (void)stopListening {
|
||||
// This releases the block on context.info.
|
||||
SCNetworkReachabilitySetCallback(_reachabilityRef, NULL, NULL);
|
||||
SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, NULL);
|
||||
}
|
||||
|
||||
- (void)setQueue:(dispatch_queue_t)queue {
|
||||
_queue = queue ?: dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (_reachabilityRef) {
|
||||
[self stopListening];
|
||||
CFRelease(_reachabilityRef);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -33,27 +33,39 @@
|
|||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class GRPCCompletionQueue;
|
||||
struct grpc_call;
|
||||
|
||||
@interface GRPCHost : NSObject
|
||||
|
||||
@property(nonatomic, readonly) NSString *address;
|
||||
@property(nonatomic, copy) NSString *userAgentPrefix;
|
||||
@property(nonatomic, copy, nullable) NSString *userAgentPrefix;
|
||||
|
||||
/** The following properties should only be modified for testing: */
|
||||
|
||||
@property(nonatomic, getter=isSecure) BOOL secure;
|
||||
|
||||
@property(nonatomic, copy) NSString *pathToCertificates;
|
||||
@property(nonatomic, copy) NSString *hostNameOverride;
|
||||
@property(nonatomic, copy, nullable) NSString *pathToCertificates;
|
||||
@property(nonatomic, copy, nullable) NSString *hostNameOverride;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
/** Host objects initialized with the same address are the same. */
|
||||
+ (instancetype)hostWithAddress:(NSString *)address;
|
||||
- (instancetype)initWithAddress:(NSString *)address NS_DESIGNATED_INITIALIZER;
|
||||
+ (nullable instancetype)hostWithAddress:(NSString *)address;
|
||||
- (nullable instancetype)initWithAddress:(NSString *)address NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** Create a grpc_call object to the provided path on this host. */
|
||||
- (struct grpc_call *)unmanagedCallWithPath:(NSString *)path
|
||||
completionQueue:(GRPCCompletionQueue *)queue;
|
||||
- (nullable struct grpc_call *)unmanagedCallWithPath:(NSString *)path
|
||||
completionQueue:(GRPCCompletionQueue *)queue;
|
||||
|
||||
// TODO: There's a race when a new RPC is coming through just as an existing one is getting
|
||||
// notified that there's no connectivity. If connectivity comes back at that moment, the new RPC
|
||||
// will have its channel destroyed by the other RPC, and will never get notified of a problem, so
|
||||
// it'll hang (the C layer logs a timeout, with exponential back off). One solution could be to pass
|
||||
// the GRPCChannel to the GRPCCall, renaming this as "disconnectChannel:channel", which would only
|
||||
// act on that specific channel.
|
||||
- (void)disconnect;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
|||
|
|
@ -34,33 +34,30 @@
|
|||
#import "GRPCHost.h"
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
#import <GRPCClient/GRPCCall.h>
|
||||
#import <GRPCClient/GRPCCall+ChannelArg.h>
|
||||
|
||||
#import "GRPCChannel.h"
|
||||
#import "GRPCCompletionQueue.h"
|
||||
#import "NSDictionary+GRPC.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// TODO(jcanizales): Generate the version in a standalone header, from templates. Like
|
||||
// templates/src/core/surface/version.c.template .
|
||||
#define GRPC_OBJC_VERSION_STRING @"0.13.0"
|
||||
|
||||
@interface GRPCHost ()
|
||||
// TODO(mlumish): Investigate whether caching channels with strong links is a good idea.
|
||||
@property(nonatomic, strong) GRPCChannel *channel;
|
||||
@end
|
||||
@implementation GRPCHost {
|
||||
// TODO(mlumish): Investigate whether caching channels with strong links is a good idea.
|
||||
GRPCChannel *_channel;
|
||||
}
|
||||
|
||||
@implementation GRPCHost
|
||||
|
||||
+ (instancetype)hostWithAddress:(NSString *)address {
|
||||
+ (nullable instancetype)hostWithAddress:(NSString *)address {
|
||||
return [[self alloc] initWithAddress:address];
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
return [self initWithAddress:nil];
|
||||
}
|
||||
|
||||
// Default initializer.
|
||||
- (instancetype)initWithAddress:(NSString *)address {
|
||||
- (nullable instancetype)initWithAddress:(NSString *)address {
|
||||
if (!address) {
|
||||
return nil;
|
||||
}
|
||||
|
|
@ -95,46 +92,45 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue {
|
||||
if (!queue || !path || !self.channel) {
|
||||
return NULL;
|
||||
- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path
|
||||
completionQueue:(GRPCCompletionQueue *)queue {
|
||||
GRPCChannel *channel;
|
||||
// This is racing -[GRPCHost disconnect].
|
||||
@synchronized(self) {
|
||||
if (!_channel) {
|
||||
_channel = [self newChannel];
|
||||
}
|
||||
channel = _channel;
|
||||
}
|
||||
return grpc_channel_create_call(self.channel.unmanagedChannel,
|
||||
NULL, GRPC_PROPAGATE_DEFAULTS,
|
||||
queue.unmanagedQueue,
|
||||
path.UTF8String,
|
||||
self.hostName.UTF8String,
|
||||
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
|
||||
return [channel unmanagedCallWithPath:path completionQueue:queue];
|
||||
}
|
||||
|
||||
- (GRPCChannel *)channel {
|
||||
// Create it lazily, because we don't want to open a connection just because someone is
|
||||
// configuring a host.
|
||||
- (NSDictionary *)channelArgs {
|
||||
NSMutableDictionary *args = [NSMutableDictionary dictionary];
|
||||
|
||||
if (!_channel) {
|
||||
NSMutableDictionary *args = [NSMutableDictionary dictionary];
|
||||
|
||||
// TODO(jcanizales): Add OS and device information (see
|
||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#user-agents ).
|
||||
NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING;
|
||||
if (_userAgentPrefix) {
|
||||
userAgent = [@[_userAgentPrefix, userAgent] componentsJoinedByString:@" "];
|
||||
}
|
||||
args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent;
|
||||
|
||||
if (_secure) {
|
||||
if (_hostNameOverride) {
|
||||
args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride;
|
||||
}
|
||||
|
||||
_channel = [GRPCChannel secureChannelWithHost:_address
|
||||
pathToCertificates:_pathToCertificates
|
||||
channelArgs:args];
|
||||
} else {
|
||||
_channel = [GRPCChannel insecureChannelWithHost:_address channelArgs:args];
|
||||
}
|
||||
// TODO(jcanizales): Add OS and device information (see
|
||||
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#user-agents ).
|
||||
NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING;
|
||||
if (_userAgentPrefix) {
|
||||
userAgent = [_userAgentPrefix stringByAppendingFormat:@" %@", userAgent];
|
||||
}
|
||||
args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent;
|
||||
|
||||
if (_secure && _hostNameOverride) {
|
||||
args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride;
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
- (GRPCChannel *)newChannel {
|
||||
NSDictionary *args = [self channelArgs];
|
||||
if (_secure) {
|
||||
return [GRPCChannel secureChannelWithHost:_address
|
||||
pathToCertificates:_pathToCertificates
|
||||
channelArgs:args];
|
||||
} else {
|
||||
return [GRPCChannel insecureChannelWithHost:_address channelArgs:args];
|
||||
}
|
||||
return _channel;
|
||||
}
|
||||
|
||||
- (NSString *)hostName {
|
||||
|
|
@ -142,7 +138,16 @@
|
|||
return _hostNameOverride ?: _address;
|
||||
}
|
||||
|
||||
- (void)disconnect {
|
||||
// This is racing -[GRPCHost unmanagedCallWithPath:completionQueue:].
|
||||
@synchronized(self) {
|
||||
_channel = nil;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(jcanizales): Don't let set |secure| to |NO| if |pathToCertificates| or |hostNameOverride|
|
||||
// have been set. Don't let set either of the latter if |secure| has been set to |NO|.
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* "X-macro" file that lists the flags names of Apple's Network Reachability API, along with a nice
|
||||
* Objective-C method name used to query each of them.
|
||||
*
|
||||
* Example usage: To generate a dictionary from flag value to name, one can do:
|
||||
|
||||
NSDictionary *flagNames = @{
|
||||
#define GRPC_XMACRO_ITEM(methodName, FlagName) \
|
||||
@(kSCNetworkReachabilityFlags ## FlagName): @#methodName,
|
||||
#include "GRXReachabilityFlagNames.xmacro.h"
|
||||
#undef GRPC_XMACRO_ITEM
|
||||
};
|
||||
|
||||
XCTAssertEqualObjects(flagNames[@(kSCNetworkReachabilityFlagsIsWWAN)], @"isCell");
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GRPC_XMACRO_ITEM
|
||||
#error This file is to be used with the "X-macro" pattern: Please #define \
|
||||
GRPC_XMACRO_ITEM(methodName, FlagName), then #include this file, and then #undef \
|
||||
GRPC_XMACRO_ITEM.
|
||||
#endif
|
||||
|
||||
GRPC_XMACRO_ITEM(isCell, IsWWAN)
|
||||
GRPC_XMACRO_ITEM(reachable, Reachable)
|
||||
GRPC_XMACRO_ITEM(transientConnection, TransientConnection)
|
||||
GRPC_XMACRO_ITEM(connectionRequired, ConnectionRequired)
|
||||
GRPC_XMACRO_ITEM(connectionOnTraffic, ConnectionOnTraffic)
|
||||
GRPC_XMACRO_ITEM(interventionRequired, InterventionRequired)
|
||||
GRPC_XMACRO_ITEM(connectionOnDemand, ConnectionOnDemand)
|
||||
GRPC_XMACRO_ITEM(isLocalAddress, IsLocalAddress)
|
||||
GRPC_XMACRO_ITEM(isDirect, IsDirect)
|
||||
|
|
@ -34,7 +34,6 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#include <grpc/grpc.h>
|
||||
|
||||
#import "GRPCChannel.h"
|
||||
#import "GRPCRequestHeaders.h"
|
||||
|
||||
@interface GRPCOperation : NSObject
|
||||
|
|
@ -94,4 +93,5 @@
|
|||
- (void)startBatchWithOperations:(NSArray *)ops;
|
||||
|
||||
- (void)cancel;
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -42,11 +42,42 @@
|
|||
if (!handler) {
|
||||
return [[self alloc] init];
|
||||
}
|
||||
return [[self alloc] initWithValueHandler:^(id value) {
|
||||
handler(value, nil);
|
||||
} completionHandler:^(NSError *errorOrNil) {
|
||||
if (errorOrNil) {
|
||||
handler(nil, errorOrNil);
|
||||
// We nilify this variable when the block is invoked, so that handler is only invoked once even if
|
||||
// the writer tries to write multiple values.
|
||||
__block GRXEventHandler eventHandler = ^(BOOL done, id value, NSError *error) {
|
||||
// Nillify eventHandler before invoking handler, in case the latter causes the former to be
|
||||
// executed recursively. Because blocks can be deallocated even during execution, we have to
|
||||
// first retain handler locally to guarantee it's valid.
|
||||
// TODO(jcanizales): Just turn this craziness into a simple subclass of GRXWriteable.
|
||||
GRXSingleHandler singleHandler = handler;
|
||||
eventHandler = nil;
|
||||
|
||||
if (value) {
|
||||
singleHandler(value, nil);
|
||||
} else if (error) {
|
||||
singleHandler(nil, error);
|
||||
} else {
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: @"The writer finished without producing any value."
|
||||
};
|
||||
// Even though RxLibrary is independent of gRPC, the domain and code here are, for the moment,
|
||||
// set to the values of kGRPCErrorDomain and GRPCErrorCodeInternal. This way, the error formed
|
||||
// is the one user of gRPC would expect if the server failed to produce a response.
|
||||
//
|
||||
// TODO(jcanizales): Figure out a way to keep errors of RxLibrary generic without making users
|
||||
// of gRPC take care of two different error domains and error code enums. A possibility is to
|
||||
// add error handling to GRXWriters or GRXWriteables, and use them to translate errors between
|
||||
// the two domains.
|
||||
static NSString *kGRPCErrorDomain = @"io.grpc";
|
||||
static NSUInteger kGRPCErrorCodeInternal = 13;
|
||||
singleHandler(nil, [NSError errorWithDomain:kGRPCErrorDomain
|
||||
code:kGRPCErrorCodeInternal
|
||||
userInfo:userInfo]);
|
||||
}
|
||||
};
|
||||
return [self writeableWithEventHandler:^(BOOL done, id value, NSError *error) {
|
||||
if (eventHandler) {
|
||||
eventHandler(done, value, error);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,10 +273,12 @@ static ProtoMethod *kUnaryCallMethod;
|
|||
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
|
||||
XCTAssertNotNil(value, @"nil value received as response.");
|
||||
XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
|
||||
/* This test needs to be more clever in regards to changing the version of the core.
|
||||
XCTAssertEqualObjects(call.responseHeaders[@"x-grpc-test-echo-useragent"],
|
||||
@"Foo grpc-objc/0.13.0 grpc-c/0.14.0-dev (ios)",
|
||||
@"Did not receive expected user agent %@",
|
||||
call.responseHeaders[@"x-grpc-test-echo-useragent"]);
|
||||
*/
|
||||
[response fulfill];
|
||||
} completionHandler:^(NSError *errorOrNil) {
|
||||
XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@
|
|||
}
|
||||
@end
|
||||
|
||||
// TODO(jcanizales): Split into one file per tested class.
|
||||
|
||||
@interface RxLibraryUnitTests : XCTestCase
|
||||
@end
|
||||
|
||||
|
|
@ -79,6 +81,7 @@
|
|||
// If:
|
||||
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
|
||||
[writeable writeValue:anyValue];
|
||||
[writeable writesFinishedWithError:nil];
|
||||
|
||||
// Then:
|
||||
XCTAssertEqual(handler.timesCalled, 1);
|
||||
|
|
@ -101,6 +104,54 @@
|
|||
XCTAssertEqualObjects(handler.errorOrNil, anyError);
|
||||
}
|
||||
|
||||
- (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenError {
|
||||
// Given:
|
||||
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
|
||||
id anyValue = @7;
|
||||
NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
|
||||
|
||||
// If:
|
||||
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
|
||||
[writeable writeValue:anyValue];
|
||||
[writeable writesFinishedWithError:anyError];
|
||||
|
||||
// Then:
|
||||
XCTAssertEqual(handler.timesCalled, 1);
|
||||
XCTAssertEqualObjects(handler.value, anyValue);
|
||||
XCTAssertEqualObjects(handler.errorOrNil, nil);
|
||||
}
|
||||
|
||||
- (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenValue {
|
||||
// Given:
|
||||
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
|
||||
id anyValue = @7;
|
||||
|
||||
// If:
|
||||
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
|
||||
[writeable writeValue:anyValue];
|
||||
[writeable writeValue:anyValue];
|
||||
[writeable writesFinishedWithError:nil];
|
||||
|
||||
// Then:
|
||||
XCTAssertEqual(handler.timesCalled, 1);
|
||||
XCTAssertEqualObjects(handler.value, anyValue);
|
||||
XCTAssertEqualObjects(handler.errorOrNil, nil);
|
||||
}
|
||||
|
||||
- (void)testWriteableSingleHandlerFailsOnEmptyWriter {
|
||||
// Given:
|
||||
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
|
||||
|
||||
// If:
|
||||
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
|
||||
[writeable writesFinishedWithError:nil];
|
||||
|
||||
// Then:
|
||||
XCTAssertEqual(handler.timesCalled, 1);
|
||||
XCTAssertEqualObjects(handler.value, nil);
|
||||
XCTAssertNotNil(handler.errorOrNil);
|
||||
}
|
||||
|
||||
#pragma mark BufferedPipe
|
||||
|
||||
- (void)testBufferedPipePropagatesValue {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
{
|
||||
"name": "grpc/grpc",
|
||||
"type": "library",
|
||||
"description": "gRPC library for PHP",
|
||||
"version": "0.6.0",
|
||||
"version": "0.14.0",
|
||||
"keywords": ["rpc"],
|
||||
"homepage": "http://grpc.io",
|
||||
"license": "BSD-3-Clause",
|
||||
"repositories": [
|
||||
|
|
@ -13,7 +15,7 @@
|
|||
"require": {
|
||||
"php": ">=5.5.0",
|
||||
"datto/protobuf-php": "dev-master",
|
||||
"google/auth": "dev-master"
|
||||
"google/auth": "v0.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
gRPC PHP Extension
|
||||
==================
|
||||
|
||||
# Requirements
|
||||
|
||||
* PHP 5.5+
|
||||
* [gRPC core library](https://github.com/grpc/grpc) 0.11.0
|
||||
|
||||
# Installation
|
||||
|
||||
## Install PHP 5
|
||||
|
||||
```
|
||||
$ sudo apt-get install git php5 php5-dev php-pear unzip
|
||||
```
|
||||
|
||||
## Compile gRPC Core Library
|
||||
|
||||
Clone the gRPC source code repository
|
||||
|
||||
```
|
||||
$ git clone https://github.com/grpc/grpc.git
|
||||
```
|
||||
|
||||
Build and install the gRPC C core libraries
|
||||
|
||||
```sh
|
||||
$ cd grpc
|
||||
$ git checkout --track origin/release-0_11
|
||||
$ git pull --recurse-submodules && git submodule update --init --recursive
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
Note: you may encounter a warning about the Protobuf compiler `protoc` 3.0.0+ not being installed. The following might help, and will be useful later on when we need to compile the `protoc-gen-php` tool.
|
||||
|
||||
```sh
|
||||
$ cd grpc/third_party/protobuf
|
||||
$ sudo make install # 'make' should have been run by core grpc
|
||||
```
|
||||
|
||||
## Install the gRPC PHP extension
|
||||
|
||||
Quick install
|
||||
|
||||
```sh
|
||||
$ sudo pecl install grpc
|
||||
```
|
||||
|
||||
Note: before a stable release, you may need to do
|
||||
|
||||
```sh
|
||||
$ sudo pecl install grpc-beta
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
Compile from source
|
||||
|
||||
```sh
|
||||
$ # from grpc
|
||||
$ cd src/php/ext/grpc
|
||||
$ phpize
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -43,7 +43,9 @@ function p($line)
|
|||
|
||||
$host = 'localhost:50051';
|
||||
p("Connecting to host: $host");
|
||||
$client = new math\MathClient($host, []);
|
||||
$client = new math\MathClient($host, [
|
||||
'credentials' => Grpc\ChannelCredentials::createInsecure()
|
||||
]);
|
||||
p('Client class: '.get_class($client));
|
||||
p('');
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ message RequestParams {
|
|||
bool echo_peer = 7;
|
||||
string expected_client_identity = 8; // will force check_auth_context.
|
||||
bool skip_cancelled_check = 9;
|
||||
string expected_transport_security_type = 10;
|
||||
}
|
||||
|
||||
message EchoRequest {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Package for gRPC Python.
|
|||
Installation
|
||||
------------
|
||||
|
||||
gRPC Python is available for Linux and Mac OS X running Python 2.7.
|
||||
gRPC Python is available for Linux, Mac OS X, and Windows running Python 2.7.
|
||||
|
||||
From PyPI
|
||||
~~~~~~~~~
|
||||
|
|
@ -23,11 +23,15 @@ Else system wide (on Ubuntu)...
|
|||
|
||||
$ sudo pip install grpcio
|
||||
|
||||
n.b. On Windows and on Mac OS X one *must* have a recent release of :code:`pip`
|
||||
to retrieve the proper wheel from PyPI. Be sure to upgrade to the latest
|
||||
version!
|
||||
|
||||
From Source
|
||||
~~~~~~~~~~~
|
||||
|
||||
Building from source requires that you have the Python headers (usually a
|
||||
package named `python-dev`).
|
||||
package named :code:`python-dev`).
|
||||
|
||||
::
|
||||
|
||||
|
|
@ -36,8 +40,8 @@ package named `python-dev`).
|
|||
$ cd $REPO_ROOT
|
||||
$ pip install .
|
||||
|
||||
Note that `$REPO_ROOT` can be assigned to whatever directory name floats your
|
||||
fancy.
|
||||
Note that :code:`$REPO_ROOT` can be assigned to whatever directory name floats
|
||||
your fancy.
|
||||
|
||||
Troubleshooting
|
||||
~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -119,8 +119,7 @@ class SphinxDocumentation(setuptools.Command):
|
|||
import sphinx
|
||||
import sphinx.apidoc
|
||||
metadata = self.distribution.metadata
|
||||
src_dir = os.path.join(
|
||||
PYTHON_STEM, self.distribution.package_dir[''], 'grpc')
|
||||
src_dir = os.path.join(PYTHON_STEM, 'grpc')
|
||||
sys.path.append(src_dir)
|
||||
sphinx.apidoc.main([
|
||||
'', '--force', '--full', '-H', metadata.name, '-A', metadata.author,
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ cdef class Channel:
|
|||
self, grpc_connectivity_state last_observed_state,
|
||||
Timespec deadline not None, CompletionQueue queue not None, tag):
|
||||
cdef OperationTag operation_tag = OperationTag(tag)
|
||||
operation_tag.references = [self, queue]
|
||||
cpython.Py_INCREF(operation_tag)
|
||||
grpc_channel_watch_connectivity_state(
|
||||
self.c_channel, last_observed_state, deadline.c_time,
|
||||
|
|
|
|||
|
|
@ -140,7 +140,8 @@ cdef class CompletionQueue:
|
|||
grpc_completion_queue_shutdown(self.c_completion_queue)
|
||||
# Pump the queue
|
||||
while not self.is_shutdown:
|
||||
event = grpc_completion_queue_next(
|
||||
self.c_completion_queue, c_deadline, NULL)
|
||||
with nogil:
|
||||
event = grpc_completion_queue_next(
|
||||
self.c_completion_queue, c_deadline, NULL)
|
||||
self._interpret_event(event)
|
||||
grpc_completion_queue_destroy(self.c_completion_queue)
|
||||
|
|
|
|||
|
|
@ -106,7 +106,6 @@ cdef class Server:
|
|||
self.is_shutting_down = True
|
||||
operation_tag = OperationTag(tag)
|
||||
operation_tag.shutting_down_server = self
|
||||
operation_tag.references.extend([self, queue])
|
||||
cpython.Py_INCREF(operation_tag)
|
||||
grpc_server_shutdown_and_notify(
|
||||
self.c_server, queue.c_completion_queue,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import os
|
|||
import platform
|
||||
import shutil
|
||||
import sys
|
||||
import sysconfig
|
||||
|
||||
import setuptools
|
||||
|
||||
|
|
@ -51,9 +52,15 @@ USE_PRECOMPILED_BINARIES = bool(int(os.environ.get(
|
|||
|
||||
def _tagged_ext_name(base):
|
||||
uname = platform.uname()
|
||||
tags = '-'.join((grpc_version.VERSION, uname[0], uname[4]))
|
||||
flavor = 'ucs2' if sys.maxunicode == 65535 else 'ucs4'
|
||||
return '{base}-{tags}-{flavor}'.format(base=base, tags=tags, flavor=flavor)
|
||||
tags = (
|
||||
grpc_version.VERSION,
|
||||
'py{}'.format(sysconfig.get_python_version()),
|
||||
uname[0],
|
||||
uname[4],
|
||||
)
|
||||
ucs = 'ucs{}'.format(sysconfig.get_config_var('Py_UNICODE_SIZE'))
|
||||
return '{base}-{tags}-{ucs}'.format(
|
||||
base=base, tags='-'.join(tags), ucs=ucs)
|
||||
|
||||
|
||||
class BuildTaggedExt(setuptools.Command):
|
||||
|
|
|
|||
|
|
@ -43,6 +43,13 @@ import uuid
|
|||
from tests import _loader
|
||||
from tests import _result
|
||||
|
||||
# This number needs to be large enough to outpace output on stdout and stderr
|
||||
# from the gRPC core, otherwise we could end up in a potential deadlock. This
|
||||
# stems from the OS waiting on someone to clear a filled pipe buffer while the
|
||||
# GIL is held from a write to stderr from gRPC core, but said someone is in
|
||||
# Python code thus necessitating GIL acquisition.
|
||||
_READ_BYTES = 2**20
|
||||
|
||||
|
||||
class CapturePipe(object):
|
||||
"""A context-manager pipe to redirect output to a byte array.
|
||||
|
|
@ -76,6 +83,10 @@ class CapturePipe(object):
|
|||
flags = fcntl.fcntl(self._read_fd, fcntl.F_GETFL)
|
||||
fcntl.fcntl(self._read_fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
||||
self._read_thread = threading.Thread(target=self._read)
|
||||
# If the user wants to exit from the Python program and hits ctrl-C and the
|
||||
# read thread is somehow deadlocked with something else, the Python code may
|
||||
# refuse to exit. This prevents that by making the read thread second-class.
|
||||
self._read_thread.daemon = True
|
||||
self._read_thread.start()
|
||||
|
||||
def stop(self):
|
||||
|
|
@ -93,7 +104,7 @@ class CapturePipe(object):
|
|||
self.output = bytearray()
|
||||
while True:
|
||||
select.select([self._read_fd], [], [])
|
||||
read_bytes = os.read(self._read_fd, 1024)
|
||||
read_bytes = os.read(self._read_fd, _READ_BYTES)
|
||||
if read_bytes:
|
||||
self.output.extend(read_bytes)
|
||||
else:
|
||||
|
|
@ -144,7 +155,7 @@ class Runner(object):
|
|||
def run(self, suite):
|
||||
"""See setuptools' test_runner setup argument for information."""
|
||||
# only run test cases with id starting with given prefix
|
||||
testcase_filter = os.getenv('GPRC_PYTHON_TESTRUNNER_FILTER')
|
||||
testcase_filter = os.getenv('GRPC_PYTHON_TESTRUNNER_FILTER')
|
||||
filtered_cases = []
|
||||
for case in _loader.iterate_suite_cases(suite):
|
||||
if not testcase_filter or case.id().startswith(testcase_filter):
|
||||
|
|
|
|||
|
|
@ -12,31 +12,22 @@
|
|||
"_core_over_links_base_interface_test.SyncEasyTest",
|
||||
"_core_over_links_base_interface_test.SyncPeasyTest",
|
||||
"_crust_over_core_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest",
|
||||
"_crust_over_core_face_interface_test.DynamicInvokerEventInvocationSynchronousEventServiceTest",
|
||||
"_crust_over_core_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest",
|
||||
"_crust_over_core_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest",
|
||||
"_crust_over_core_face_interface_test.GenericInvokerEventInvocationSynchronousEventServiceTest",
|
||||
"_crust_over_core_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest",
|
||||
"_crust_over_core_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest",
|
||||
"_crust_over_core_face_interface_test.MultiCallableInvokerEventInvocationSynchronousEventServiceTest",
|
||||
"_crust_over_core_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest",
|
||||
"_crust_over_core_over_links_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest",
|
||||
"_crust_over_core_over_links_face_interface_test.DynamicInvokerEventInvocationSynchronousEventServiceTest",
|
||||
"_crust_over_core_over_links_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest",
|
||||
"_crust_over_core_over_links_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest",
|
||||
"_crust_over_core_over_links_face_interface_test.GenericInvokerEventInvocationSynchronousEventServiceTest",
|
||||
"_crust_over_core_over_links_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest",
|
||||
"_crust_over_core_over_links_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest",
|
||||
"_crust_over_core_over_links_face_interface_test.MultiCallableInvokerEventInvocationSynchronousEventServiceTest",
|
||||
"_crust_over_core_over_links_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest",
|
||||
"_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest",
|
||||
"_face_interface_test.DynamicInvokerEventInvocationSynchronousEventServiceTest",
|
||||
"_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest",
|
||||
"_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest",
|
||||
"_face_interface_test.GenericInvokerEventInvocationSynchronousEventServiceTest",
|
||||
"_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest",
|
||||
"_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest",
|
||||
"_face_interface_test.MultiCallableInvokerEventInvocationSynchronousEventServiceTest",
|
||||
"_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest",
|
||||
"_implementations_test.ChannelCredentialsTest",
|
||||
"_insecure_interop_test.InsecureInteropTest",
|
||||
|
|
|
|||
|
|
@ -1,381 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""Test code for the Face layer of RPC Framework."""
|
||||
|
||||
import abc
|
||||
import unittest
|
||||
|
||||
# test_interfaces is referenced from specification in this module.
|
||||
from grpc.framework.interfaces.face import face
|
||||
from tests.unit.framework.common import test_constants
|
||||
from tests.unit.framework.common import test_control
|
||||
from tests.unit.framework.common import test_coverage
|
||||
from tests.unit.framework.interfaces.face import _3069_test_constant
|
||||
from tests.unit.framework.interfaces.face import _digest
|
||||
from tests.unit.framework.interfaces.face import _receiver
|
||||
from tests.unit.framework.interfaces.face import _stock_service
|
||||
from tests.unit.framework.interfaces.face import test_interfaces # pylint: disable=unused-import
|
||||
|
||||
|
||||
class TestCase(test_coverage.Coverage, unittest.TestCase):
|
||||
"""A test of the Face layer of RPC Framework.
|
||||
|
||||
Concrete subclasses must have an "implementation" attribute of type
|
||||
test_interfaces.Implementation and an "invoker_constructor" attribute of type
|
||||
_invocation.InvokerConstructor.
|
||||
"""
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
NAME = 'EventInvocationSynchronousEventServiceTest'
|
||||
|
||||
def setUp(self):
|
||||
"""See unittest.TestCase.setUp for full specification.
|
||||
|
||||
Overriding implementations must call this implementation.
|
||||
"""
|
||||
self._control = test_control.PauseFailControl()
|
||||
self._digest = _digest.digest(
|
||||
_stock_service.STOCK_TEST_SERVICE, self._control, None)
|
||||
|
||||
generic_stub, dynamic_stubs, self._memo = self.implementation.instantiate(
|
||||
self._digest.methods, self._digest.event_method_implementations, None)
|
||||
self._invoker = self.invoker_constructor.construct_invoker(
|
||||
generic_stub, dynamic_stubs, self._digest.methods)
|
||||
|
||||
def tearDown(self):
|
||||
"""See unittest.TestCase.tearDown for full specification.
|
||||
|
||||
Overriding implementations must call this implementation.
|
||||
"""
|
||||
self._invoker = None
|
||||
self.implementation.destantiate(self._memo)
|
||||
|
||||
def testSuccessfulUnaryRequestUnaryResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_unary_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
request = test_messages.request()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
self._invoker.event(group, method)(
|
||||
request, receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
receiver.block_until_terminated()
|
||||
response = receiver.unary_response()
|
||||
|
||||
test_messages.verify(request, response, self)
|
||||
|
||||
def testSuccessfulUnaryRequestStreamResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_stream_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
request = test_messages.request()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
self._invoker.event(group, method)(
|
||||
request, receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
receiver.block_until_terminated()
|
||||
responses = receiver.stream_responses()
|
||||
|
||||
test_messages.verify(request, responses, self)
|
||||
|
||||
def testSuccessfulStreamRequestUnaryResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.stream_unary_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
requests = test_messages.requests()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
call_consumer = self._invoker.event(group, method)(
|
||||
receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
for request in requests:
|
||||
call_consumer.consume(request)
|
||||
call_consumer.terminate()
|
||||
receiver.block_until_terminated()
|
||||
response = receiver.unary_response()
|
||||
|
||||
test_messages.verify(requests, response, self)
|
||||
|
||||
def testSuccessfulStreamRequestStreamResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.stream_stream_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
requests = test_messages.requests()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
call_consumer = self._invoker.event(group, method)(
|
||||
receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
for request in requests:
|
||||
call_consumer.consume(request)
|
||||
call_consumer.terminate()
|
||||
receiver.block_until_terminated()
|
||||
responses = receiver.stream_responses()
|
||||
|
||||
test_messages.verify(requests, responses, self)
|
||||
|
||||
def testSequentialInvocations(self):
|
||||
# pylint: disable=cell-var-from-loop
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_unary_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
first_request = test_messages.request()
|
||||
second_request = test_messages.request()
|
||||
second_receiver = _receiver.Receiver()
|
||||
|
||||
def make_second_invocation():
|
||||
self._invoker.event(group, method)(
|
||||
second_request, second_receiver, second_receiver.abort,
|
||||
test_constants.LONG_TIMEOUT)
|
||||
|
||||
class FirstReceiver(_receiver.Receiver):
|
||||
|
||||
def complete(self, terminal_metadata, code, details):
|
||||
super(FirstReceiver, self).complete(
|
||||
terminal_metadata, code, details)
|
||||
make_second_invocation()
|
||||
|
||||
first_receiver = FirstReceiver()
|
||||
|
||||
self._invoker.event(group, method)(
|
||||
first_request, first_receiver, first_receiver.abort,
|
||||
test_constants.LONG_TIMEOUT)
|
||||
second_receiver.block_until_terminated()
|
||||
|
||||
first_response = first_receiver.unary_response()
|
||||
second_response = second_receiver.unary_response()
|
||||
test_messages.verify(first_request, first_response, self)
|
||||
test_messages.verify(second_request, second_response, self)
|
||||
|
||||
def testParallelInvocations(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_unary_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
first_request = test_messages.request()
|
||||
first_receiver = _receiver.Receiver()
|
||||
second_request = test_messages.request()
|
||||
second_receiver = _receiver.Receiver()
|
||||
|
||||
self._invoker.event(group, method)(
|
||||
first_request, first_receiver, first_receiver.abort,
|
||||
test_constants.LONG_TIMEOUT)
|
||||
self._invoker.event(group, method)(
|
||||
second_request, second_receiver, second_receiver.abort,
|
||||
test_constants.LONG_TIMEOUT)
|
||||
first_receiver.block_until_terminated()
|
||||
second_receiver.block_until_terminated()
|
||||
|
||||
first_response = first_receiver.unary_response()
|
||||
second_response = second_receiver.unary_response()
|
||||
test_messages.verify(first_request, first_response, self)
|
||||
test_messages.verify(second_request, second_response, self)
|
||||
|
||||
@unittest.skip('TODO(nathaniel): implement.')
|
||||
def testWaitingForSomeButNotAllParallelInvocations(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def testCancelledUnaryRequestUnaryResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_unary_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
request = test_messages.request()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
with self._control.pause():
|
||||
call = self._invoker.event(group, method)(
|
||||
request, receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
call.cancel()
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(face.Abortion.Kind.CANCELLED, receiver.abortion().kind)
|
||||
|
||||
def testCancelledUnaryRequestStreamResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_stream_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
request = test_messages.request()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
call = self._invoker.event(group, method)(
|
||||
request, receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
call.cancel()
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(face.Abortion.Kind.CANCELLED, receiver.abortion().kind)
|
||||
|
||||
def testCancelledStreamRequestUnaryResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.stream_unary_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
requests = test_messages.requests()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
call_consumer = self._invoker.event(group, method)(
|
||||
receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
for request in requests:
|
||||
call_consumer.consume(request)
|
||||
call_consumer.cancel()
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(face.Abortion.Kind.CANCELLED, receiver.abortion().kind)
|
||||
|
||||
def testCancelledStreamRequestStreamResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.stream_stream_messages_sequences.iteritems()):
|
||||
for unused_test_messages in test_messages_sequence:
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
call_consumer = self._invoker.event(group, method)(
|
||||
receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
call_consumer.cancel()
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(face.Abortion.Kind.CANCELLED, receiver.abortion().kind)
|
||||
|
||||
def testExpiredUnaryRequestUnaryResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_unary_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
request = test_messages.request()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
with self._control.pause():
|
||||
self._invoker.event(group, method)(
|
||||
request, receiver, receiver.abort,
|
||||
_3069_test_constant.REALLY_SHORT_TIMEOUT)
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(face.Abortion.Kind.EXPIRED, receiver.abortion().kind)
|
||||
|
||||
def testExpiredUnaryRequestStreamResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_stream_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
request = test_messages.request()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
with self._control.pause():
|
||||
self._invoker.event(group, method)(
|
||||
request, receiver, receiver.abort,
|
||||
_3069_test_constant.REALLY_SHORT_TIMEOUT)
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(face.Abortion.Kind.EXPIRED, receiver.abortion().kind)
|
||||
|
||||
def testExpiredStreamRequestUnaryResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.stream_unary_messages_sequences.iteritems()):
|
||||
for unused_test_messages in test_messages_sequence:
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
self._invoker.event(group, method)(
|
||||
receiver, receiver.abort, _3069_test_constant.REALLY_SHORT_TIMEOUT)
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(face.Abortion.Kind.EXPIRED, receiver.abortion().kind)
|
||||
|
||||
def testExpiredStreamRequestStreamResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.stream_stream_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
requests = test_messages.requests()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
call_consumer = self._invoker.event(group, method)(
|
||||
receiver, receiver.abort, _3069_test_constant.REALLY_SHORT_TIMEOUT)
|
||||
for request in requests:
|
||||
call_consumer.consume(request)
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(face.Abortion.Kind.EXPIRED, receiver.abortion().kind)
|
||||
|
||||
def testFailedUnaryRequestUnaryResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_unary_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
request = test_messages.request()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
with self._control.fail():
|
||||
self._invoker.event(group, method)(
|
||||
request, receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(
|
||||
face.Abortion.Kind.REMOTE_FAILURE, receiver.abortion().kind)
|
||||
|
||||
def testFailedUnaryRequestStreamResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.unary_stream_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
request = test_messages.request()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
with self._control.fail():
|
||||
self._invoker.event(group, method)(
|
||||
request, receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(
|
||||
face.Abortion.Kind.REMOTE_FAILURE, receiver.abortion().kind)
|
||||
|
||||
def testFailedStreamRequestUnaryResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.stream_unary_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
requests = test_messages.requests()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
with self._control.fail():
|
||||
call_consumer = self._invoker.event(group, method)(
|
||||
receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
for request in requests:
|
||||
call_consumer.consume(request)
|
||||
call_consumer.terminate()
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(
|
||||
face.Abortion.Kind.REMOTE_FAILURE, receiver.abortion().kind)
|
||||
|
||||
def testFailedStreamRequestStreamResponse(self):
|
||||
for (group, method), test_messages_sequence in (
|
||||
self._digest.stream_stream_messages_sequences.iteritems()):
|
||||
for test_messages in test_messages_sequence:
|
||||
requests = test_messages.requests()
|
||||
receiver = _receiver.Receiver()
|
||||
|
||||
with self._control.fail():
|
||||
call_consumer = self._invoker.event(group, method)(
|
||||
receiver, receiver.abort, test_constants.LONG_TIMEOUT)
|
||||
for request in requests:
|
||||
call_consumer.consume(request)
|
||||
call_consumer.terminate()
|
||||
receiver.block_until_terminated()
|
||||
|
||||
self.assertIs(
|
||||
face.Abortion.Kind.REMOTE_FAILURE, receiver.abortion().kind)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2015, Google Inc.
|
||||
# Copyright 2015-2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -34,14 +34,12 @@ import unittest # pylint: disable=unused-import
|
|||
|
||||
# test_interfaces is referenced from specification in this module.
|
||||
from tests.unit.framework.interfaces.face import _blocking_invocation_inline_service
|
||||
from tests.unit.framework.interfaces.face import _event_invocation_synchronous_event_service
|
||||
from tests.unit.framework.interfaces.face import _future_invocation_asynchronous_event_service
|
||||
from tests.unit.framework.interfaces.face import _invocation
|
||||
from tests.unit.framework.interfaces.face import test_interfaces # pylint: disable=unused-import
|
||||
|
||||
_TEST_CASE_SUPERCLASSES = (
|
||||
_blocking_invocation_inline_service.TestCase,
|
||||
_event_invocation_synchronous_event_service.TestCase,
|
||||
_future_invocation_asynchronous_event_service.TestCase,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,3 +15,6 @@ Metrics/CyclomaticComplexity:
|
|||
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 8
|
||||
|
||||
Metrics/ClassLength:
|
||||
Max: 250
|
||||
|
|
|
|||
|
|
@ -107,7 +107,9 @@ module GRPC
|
|||
|
||||
# Starts running the jobs in the thread pool.
|
||||
def start
|
||||
fail 'already stopped' if @stopped
|
||||
@stop_mutex.synchronize do
|
||||
fail 'already stopped' if @stopped
|
||||
end
|
||||
until @workers.size == @size.to_i
|
||||
next_thread = Thread.new do
|
||||
catch(:exit) do # allows { throw :exit } to kill a thread
|
||||
|
|
@ -264,10 +266,10 @@ module GRPC
|
|||
@pool = Pool.new(@pool_size)
|
||||
@run_cond = ConditionVariable.new
|
||||
@run_mutex = Mutex.new
|
||||
@running = false
|
||||
# running_state can take 4 values: :not_started, :running, :stopping, and
|
||||
# :stopped. State transitions can only proceed in that order.
|
||||
@running_state = :not_started
|
||||
@server = RpcServer.setup_srv(server_override, @cq, **kw)
|
||||
@stopped = false
|
||||
@stop_mutex = Mutex.new
|
||||
end
|
||||
|
||||
# stops a running server
|
||||
|
|
@ -275,27 +277,42 @@ module GRPC
|
|||
# the call has no impact if the server is already stopped, otherwise
|
||||
# server's current call loop is it's last.
|
||||
def stop
|
||||
return unless @running
|
||||
@stop_mutex.synchronize do
|
||||
@stopped = true
|
||||
@run_mutex.synchronize do
|
||||
fail 'Cannot stop before starting' if @running_state == :not_started
|
||||
return if @running_state != :running
|
||||
transition_running_state(:stopping)
|
||||
end
|
||||
deadline = from_relative_time(@poll_period)
|
||||
return if @server.close(@cq, deadline)
|
||||
deadline = from_relative_time(@poll_period)
|
||||
@server.close(@cq, deadline)
|
||||
@pool.stop
|
||||
end
|
||||
|
||||
# determines if the server has been stopped
|
||||
def stopped?
|
||||
@stop_mutex.synchronize do
|
||||
return @stopped
|
||||
def running_state
|
||||
@run_mutex.synchronize do
|
||||
return @running_state
|
||||
end
|
||||
end
|
||||
|
||||
# Can only be called while holding @run_mutex
|
||||
def transition_running_state(target_state)
|
||||
state_transitions = {
|
||||
not_started: :running,
|
||||
running: :stopping,
|
||||
stopping: :stopped
|
||||
}
|
||||
if state_transitions[@running_state] == target_state
|
||||
@running_state = target_state
|
||||
else
|
||||
fail "Bad server state transition: #{@running_state}->#{target_state}"
|
||||
end
|
||||
end
|
||||
|
||||
# determines if the server is currently running
|
||||
def running?
|
||||
@running
|
||||
running_state == :running
|
||||
end
|
||||
|
||||
def stopped?
|
||||
running_state == :stopped
|
||||
end
|
||||
|
||||
# Is called from other threads to wait for #run to start up the server.
|
||||
|
|
@ -304,13 +321,11 @@ module GRPC
|
|||
#
|
||||
# @param timeout [Numeric] number of seconds to wait
|
||||
# @result [true, false] true if the server is running, false otherwise
|
||||
def wait_till_running(timeout = 0.1)
|
||||
end_time, sleep_period = Time.now + timeout, (1.0 * timeout) / 100
|
||||
while Time.now < end_time
|
||||
@run_mutex.synchronize { @run_cond.wait(@run_mutex) } unless running?
|
||||
sleep(sleep_period)
|
||||
def wait_till_running(timeout = nil)
|
||||
@run_mutex.synchronize do
|
||||
@run_cond.wait(@run_mutex, timeout) if @running_state == :not_started
|
||||
return @running_state == :running
|
||||
end
|
||||
running?
|
||||
end
|
||||
|
||||
# Runs the server in its own thread, then waits for signal INT or TERM on
|
||||
|
|
@ -360,11 +375,14 @@ module GRPC
|
|||
# @param service [Object|Class] a service class or object as described
|
||||
# above
|
||||
def handle(service)
|
||||
fail 'cannot add services if the server is running' if running?
|
||||
fail 'cannot add services if the server is stopped' if stopped?
|
||||
cls = service.is_a?(Class) ? service : service.class
|
||||
assert_valid_service_class(cls)
|
||||
add_rpc_descs_for(service)
|
||||
@run_mutex.synchronize do
|
||||
unless @running_state == :not_started
|
||||
fail 'cannot add services if the server has been started'
|
||||
end
|
||||
cls = service.is_a?(Class) ? service : service.class
|
||||
assert_valid_service_class(cls)
|
||||
add_rpc_descs_for(service)
|
||||
end
|
||||
end
|
||||
|
||||
# runs the server
|
||||
|
|
@ -375,16 +393,13 @@ module GRPC
|
|||
# - #running? returns true after this is called, until #stop cause the
|
||||
# the server to stop.
|
||||
def run
|
||||
if rpc_descs.size.zero?
|
||||
GRPC.logger.warn('did not run as no services were present')
|
||||
return
|
||||
end
|
||||
@run_mutex.synchronize do
|
||||
@running = true
|
||||
@run_cond.signal
|
||||
fail 'cannot run without registering services' if rpc_descs.size.zero?
|
||||
@pool.start
|
||||
@server.start
|
||||
transition_running_state(:running)
|
||||
@run_cond.broadcast
|
||||
end
|
||||
@pool.start
|
||||
@server.start
|
||||
loop_handle_server_calls
|
||||
end
|
||||
|
||||
|
|
@ -413,9 +428,9 @@ module GRPC
|
|||
|
||||
# handles calls to the server
|
||||
def loop_handle_server_calls
|
||||
fail 'not running' unless @running
|
||||
fail 'not started' if running_state == :not_started
|
||||
loop_tag = Object.new
|
||||
until stopped?
|
||||
while running_state == :running
|
||||
begin
|
||||
an_rpc = @server.request_call(@cq, loop_tag, INFINITE_FUTURE)
|
||||
break if (!an_rpc.nil?) && an_rpc.call.nil?
|
||||
|
|
@ -430,11 +445,14 @@ module GRPC
|
|||
rescue Core::CallError, RuntimeError => e
|
||||
# these might happen for various reasonse. The correct behaviour of
|
||||
# the server is to log them and continue, if it's not shutting down.
|
||||
GRPC.logger.warn("server call failed: #{e}") unless stopped?
|
||||
if running_state == :running
|
||||
GRPC.logger.warn("server call failed: #{e}")
|
||||
end
|
||||
next
|
||||
end
|
||||
end
|
||||
@running = false
|
||||
# @running_state should be :stopping here
|
||||
@run_mutex.synchronize { transition_running_state(:stopped) }
|
||||
GRPC.logger.info("stopped: #{self}")
|
||||
end
|
||||
|
||||
|
|
@ -484,9 +502,10 @@ module GRPC
|
|||
cls.assert_rpc_descs_have_methods
|
||||
end
|
||||
|
||||
# This should be called while holding @run_mutex
|
||||
def add_rpc_descs_for(service)
|
||||
cls = service.is_a?(Class) ? service : service.class
|
||||
specs, handlers = rpc_descs, rpc_handlers
|
||||
specs, handlers = (@rpc_descs ||= {}), (@rpc_handlers ||= {})
|
||||
cls.rpc_descs.each_pair do |name, spec|
|
||||
route = "/#{cls.service_name}/#{name}".to_sym
|
||||
fail "already registered: rpc #{route} from #{spec}" if specs.key? route
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2015, Google Inc.
|
||||
# Copyright 2015-2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -220,19 +220,10 @@ describe GRPC::RpcServer do
|
|||
@srv = RpcServer.new(**opts)
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
@srv.stop
|
||||
end
|
||||
|
||||
it 'starts out false' do
|
||||
expect(@srv.stopped?).to be(false)
|
||||
end
|
||||
|
||||
it 'stays false after a #stop is called before #run' do
|
||||
@srv.stop
|
||||
expect(@srv.stopped?).to be(false)
|
||||
end
|
||||
|
||||
it 'stays false after the server starts running', server: true do
|
||||
@srv.handle(EchoService)
|
||||
t = Thread.new { @srv.run }
|
||||
|
|
@ -247,8 +238,8 @@ describe GRPC::RpcServer do
|
|||
t = Thread.new { @srv.run }
|
||||
@srv.wait_till_running
|
||||
@srv.stop
|
||||
expect(@srv.stopped?).to be(true)
|
||||
t.join
|
||||
expect(@srv.stopped?).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -266,9 +257,7 @@ describe GRPC::RpcServer do
|
|||
server_override: @server
|
||||
}
|
||||
r = RpcServer.new(**opts)
|
||||
r.run
|
||||
expect(r.running?).to be(false)
|
||||
r.stop
|
||||
expect { r.run }.to raise_error(RuntimeError)
|
||||
end
|
||||
|
||||
it 'is true after run is called with a registered service' do
|
||||
|
|
@ -293,10 +282,6 @@ describe GRPC::RpcServer do
|
|||
@srv = RpcServer.new(**@opts)
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
@srv.stop
|
||||
end
|
||||
|
||||
it 'raises if #run has already been called' do
|
||||
@srv.handle(EchoService)
|
||||
t = Thread.new { @srv.run }
|
||||
|
|
@ -528,10 +513,6 @@ describe GRPC::RpcServer do
|
|||
@srv = RpcServer.new(**server_opts)
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
@srv.stop
|
||||
end
|
||||
|
||||
it 'should be added to BadStatus when requests fail', server: true do
|
||||
service = FailingService.new
|
||||
@srv.handle(service)
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@
|
|||
<contents>
|
||||
<dir baseinstalldir="/" name="/">
|
||||
<file baseinstalldir="/" name="config.m4" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/README.md" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/ext/grpc/CREDITS" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/ext/grpc/LICENSE" role="src" />
|
||||
<file baseinstalldir="/" name="src/php/ext/grpc/README.md" role="src" />
|
||||
% for source in php_config_m4.src + php_config_m4.headers:
|
||||
<file baseinstalldir="/" name="${source}" role="src" />
|
||||
% endfor
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
%YAML 1.2
|
||||
--- |
|
||||
# Copyright 2015-2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
FROM ubuntu:14.04
|
||||
|
||||
<%include file="../../apt_get_basic.include"/>
|
||||
<%include file="../../cxx_deps.include"/>
|
||||
<%include file="../../run_tests_addons.include"/>
|
||||
# Define the default command.
|
||||
CMD ["bash"]
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
%YAML 1.2
|
||||
--- |
|
||||
# Copyright 2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
FROM debian:jessie
|
||||
|
||||
<%include file="../../apt_get_basic.include"/>
|
||||
<%include file="../../csharp_deps.include"/>
|
||||
<%include file="../../cxx_deps.include"/>
|
||||
<%include file="../../node_deps.include"/>
|
||||
<%include file="../../php_deps.include"/>
|
||||
<%include file="../../ruby_deps.include"/>
|
||||
<%include file="../../python_deps.include"/>
|
||||
<%include file="../../run_tests_addons.include"/>
|
||||
# Define the default command.
|
||||
CMD ["bash"]
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "src/core/client_config/resolvers/dns_resolver.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
|
||||
#include "src/core/iomgr/resolve_address.h"
|
||||
#include "src/core/iomgr/timer.h"
|
||||
#include "test/core/util/test_config.h"
|
||||
|
||||
static void subchannel_factory_ref(grpc_subchannel_factory *scv) {}
|
||||
static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel_factory *scv) {}
|
||||
static grpc_subchannel *subchannel_factory_create_subchannel(
|
||||
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
|
||||
grpc_subchannel_args *args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const grpc_subchannel_factory_vtable sc_vtable = {
|
||||
subchannel_factory_ref, subchannel_factory_unref,
|
||||
subchannel_factory_create_subchannel};
|
||||
|
||||
static grpc_subchannel_factory sc_factory = {&sc_vtable};
|
||||
|
||||
static gpr_mu g_mu;
|
||||
static bool g_fail_resolution = true;
|
||||
|
||||
static grpc_resolved_addresses *my_resolve_address(const char *name,
|
||||
const char *addr) {
|
||||
gpr_mu_lock(&g_mu);
|
||||
GPR_ASSERT(0 == strcmp("test", name));
|
||||
if (g_fail_resolution) {
|
||||
g_fail_resolution = false;
|
||||
gpr_mu_unlock(&g_mu);
|
||||
return NULL;
|
||||
} else {
|
||||
gpr_mu_unlock(&g_mu);
|
||||
grpc_resolved_addresses *addrs = gpr_malloc(sizeof(*addrs));
|
||||
addrs->naddrs = 1;
|
||||
addrs->addrs = gpr_malloc(sizeof(*addrs->addrs));
|
||||
addrs->addrs[0].len = 123;
|
||||
return addrs;
|
||||
}
|
||||
}
|
||||
|
||||
static grpc_resolver *create_resolver(const char *name) {
|
||||
grpc_resolver_factory *factory = grpc_dns_resolver_factory_create();
|
||||
grpc_uri *uri = grpc_uri_parse(name, 0);
|
||||
GPR_ASSERT(uri);
|
||||
grpc_resolver_args args;
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.uri = uri;
|
||||
args.subchannel_factory = &sc_factory;
|
||||
grpc_resolver *resolver =
|
||||
grpc_resolver_factory_create_resolver(factory, &args);
|
||||
grpc_resolver_factory_unref(factory);
|
||||
grpc_uri_destroy(uri);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
static void on_done(grpc_exec_ctx *exec_ctx, void *ev, bool success) {
|
||||
gpr_event_set(ev, (void *)1);
|
||||
}
|
||||
|
||||
// interleave waiting for an event with a timer check
|
||||
static bool wait_loop(int deadline_seconds, gpr_event *ev) {
|
||||
while (deadline_seconds) {
|
||||
gpr_log(GPR_DEBUG, "Test: waiting for %d more seconds", deadline_seconds);
|
||||
if (gpr_event_wait(ev, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1))) return true;
|
||||
deadline_seconds--;
|
||||
|
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
||||
grpc_timer_check(&exec_ctx, gpr_now(GPR_CLOCK_MONOTONIC), NULL);
|
||||
grpc_exec_ctx_finish(&exec_ctx);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
grpc_test_init(argc, argv);
|
||||
|
||||
grpc_init();
|
||||
gpr_mu_init(&g_mu);
|
||||
grpc_blocking_resolve_address = my_resolve_address;
|
||||
|
||||
grpc_resolver *resolver = create_resolver("dns:test");
|
||||
|
||||
grpc_client_config *config = (grpc_client_config *)1;
|
||||
|
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
||||
gpr_event ev1;
|
||||
gpr_event_init(&ev1);
|
||||
grpc_resolver_next(&exec_ctx, resolver, &config,
|
||||
grpc_closure_create(on_done, &ev1));
|
||||
grpc_exec_ctx_flush(&exec_ctx);
|
||||
GPR_ASSERT(wait_loop(5, &ev1));
|
||||
GPR_ASSERT(config == NULL);
|
||||
|
||||
gpr_event ev2;
|
||||
gpr_event_init(&ev2);
|
||||
grpc_resolver_next(&exec_ctx, resolver, &config,
|
||||
grpc_closure_create(on_done, &ev2));
|
||||
grpc_exec_ctx_flush(&exec_ctx);
|
||||
GPR_ASSERT(wait_loop(30, &ev2));
|
||||
GPR_ASSERT(config != NULL);
|
||||
|
||||
grpc_client_config_unref(&exec_ctx, config);
|
||||
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test");
|
||||
grpc_exec_ctx_finish(&exec_ctx);
|
||||
|
||||
grpc_shutdown();
|
||||
gpr_mu_destroy(&g_mu);
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/useful.h>
|
||||
|
||||
#include "test/core/util/test_config.h"
|
||||
|
||||
static gpr_timespec random_deadline(void) {
|
||||
|
|
@ -57,79 +59,6 @@ static grpc_timer *create_test_elements(size_t num_elements) {
|
|||
return elems;
|
||||
}
|
||||
|
||||
static int cmp_elem(const void *a, const void *b) {
|
||||
int i = *(const int *)a;
|
||||
int j = *(const int *)b;
|
||||
return i - j;
|
||||
}
|
||||
|
||||
static size_t *all_top(grpc_timer_heap *pq, size_t *n) {
|
||||
size_t *vec = NULL;
|
||||
size_t *need_to_check_children;
|
||||
size_t num_need_to_check_children = 0;
|
||||
|
||||
*n = 0;
|
||||
if (pq->timer_count == 0) return vec;
|
||||
need_to_check_children =
|
||||
gpr_malloc(pq->timer_count * sizeof(*need_to_check_children));
|
||||
need_to_check_children[num_need_to_check_children++] = 0;
|
||||
vec = gpr_malloc(pq->timer_count * sizeof(*vec));
|
||||
while (num_need_to_check_children > 0) {
|
||||
size_t ind = need_to_check_children[0];
|
||||
size_t leftchild, rightchild;
|
||||
num_need_to_check_children--;
|
||||
memmove(need_to_check_children, need_to_check_children + 1,
|
||||
num_need_to_check_children * sizeof(*need_to_check_children));
|
||||
vec[(*n)++] = ind;
|
||||
leftchild = 1u + 2u * ind;
|
||||
if (leftchild < pq->timer_count) {
|
||||
if (gpr_time_cmp(pq->timers[leftchild]->deadline,
|
||||
pq->timers[ind]->deadline) >= 0) {
|
||||
need_to_check_children[num_need_to_check_children++] = leftchild;
|
||||
}
|
||||
rightchild = leftchild + 1;
|
||||
if (rightchild < pq->timer_count &&
|
||||
gpr_time_cmp(pq->timers[rightchild]->deadline,
|
||||
pq->timers[ind]->deadline) >= 0) {
|
||||
need_to_check_children[num_need_to_check_children++] = rightchild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gpr_free(need_to_check_children);
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
static void check_pq_top(grpc_timer *elements, grpc_timer_heap *pq,
|
||||
uint8_t *inpq, size_t num_elements) {
|
||||
gpr_timespec max_deadline = gpr_inf_past(GPR_CLOCK_REALTIME);
|
||||
size_t *max_deadline_indices =
|
||||
gpr_malloc(num_elements * sizeof(*max_deadline_indices));
|
||||
size_t *top_elements;
|
||||
size_t num_max_deadline_indices = 0;
|
||||
size_t num_top_elements;
|
||||
size_t i;
|
||||
for (i = 0; i < num_elements; ++i) {
|
||||
if (inpq[i] && gpr_time_cmp(elements[i].deadline, max_deadline) >= 0) {
|
||||
if (gpr_time_cmp(elements[i].deadline, max_deadline) > 0) {
|
||||
num_max_deadline_indices = 0;
|
||||
max_deadline = elements[i].deadline;
|
||||
}
|
||||
max_deadline_indices[num_max_deadline_indices++] = elements[i].heap_index;
|
||||
}
|
||||
}
|
||||
qsort(max_deadline_indices, num_max_deadline_indices,
|
||||
sizeof(*max_deadline_indices), cmp_elem);
|
||||
top_elements = all_top(pq, &num_top_elements);
|
||||
GPR_ASSERT(num_top_elements == num_max_deadline_indices);
|
||||
for (i = 0; i < num_top_elements; i++) {
|
||||
GPR_ASSERT(max_deadline_indices[i] == top_elements[i]);
|
||||
}
|
||||
gpr_free(max_deadline_indices);
|
||||
gpr_free(top_elements);
|
||||
}
|
||||
|
||||
static int contains(grpc_timer_heap *pq, grpc_timer *el) {
|
||||
size_t i;
|
||||
for (i = 0; i < pq->timer_count; i++) {
|
||||
|
|
@ -145,15 +74,19 @@ static void check_valid(grpc_timer_heap *pq) {
|
|||
size_t right_child = left_child + 1u;
|
||||
if (left_child < pq->timer_count) {
|
||||
GPR_ASSERT(gpr_time_cmp(pq->timers[i]->deadline,
|
||||
pq->timers[left_child]->deadline) >= 0);
|
||||
pq->timers[left_child]->deadline) <= 0);
|
||||
}
|
||||
if (right_child < pq->timer_count) {
|
||||
GPR_ASSERT(gpr_time_cmp(pq->timers[i]->deadline,
|
||||
pq->timers[right_child]->deadline) >= 0);
|
||||
pq->timers[right_child]->deadline) <= 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* test1
|
||||
*/
|
||||
|
||||
static void test1(void) {
|
||||
grpc_timer_heap pq;
|
||||
const size_t num_test_elements = 200;
|
||||
|
|
@ -162,6 +95,8 @@ static void test1(void) {
|
|||
grpc_timer *test_elements = create_test_elements(num_test_elements);
|
||||
uint8_t *inpq = gpr_malloc(num_test_elements);
|
||||
|
||||
gpr_log(GPR_INFO, "test1");
|
||||
|
||||
grpc_timer_heap_init(&pq);
|
||||
memset(inpq, 0, num_test_elements);
|
||||
GPR_ASSERT(grpc_timer_heap_is_empty(&pq));
|
||||
|
|
@ -172,7 +107,6 @@ static void test1(void) {
|
|||
check_valid(&pq);
|
||||
GPR_ASSERT(contains(&pq, &test_elements[i]));
|
||||
inpq[i] = 1;
|
||||
check_pq_top(test_elements, &pq, inpq, num_test_elements);
|
||||
}
|
||||
for (i = 0; i < num_test_elements; ++i) {
|
||||
/* Test that check still succeeds even for element that wasn't just
|
||||
|
|
@ -182,7 +116,7 @@ static void test1(void) {
|
|||
|
||||
GPR_ASSERT(pq.timer_count == num_test_elements);
|
||||
|
||||
check_pq_top(test_elements, &pq, inpq, num_test_elements);
|
||||
check_valid(&pq);
|
||||
|
||||
for (i = 0; i < num_test_operations; ++i) {
|
||||
size_t elem_num = (size_t)rand() % num_test_elements;
|
||||
|
|
@ -193,14 +127,12 @@ static void test1(void) {
|
|||
grpc_timer_heap_add(&pq, el);
|
||||
GPR_ASSERT(contains(&pq, el));
|
||||
inpq[elem_num] = 1;
|
||||
check_pq_top(test_elements, &pq, inpq, num_test_elements);
|
||||
check_valid(&pq);
|
||||
} else {
|
||||
GPR_ASSERT(contains(&pq, el));
|
||||
grpc_timer_heap_remove(&pq, el);
|
||||
GPR_ASSERT(!contains(&pq, el));
|
||||
inpq[elem_num] = 0;
|
||||
check_pq_top(test_elements, &pq, inpq, num_test_elements);
|
||||
check_valid(&pq);
|
||||
}
|
||||
}
|
||||
|
|
@ -210,7 +142,108 @@ static void test1(void) {
|
|||
gpr_free(inpq);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* test2
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
grpc_timer elem;
|
||||
bool inserted;
|
||||
} elem_struct;
|
||||
|
||||
static elem_struct *search_elems(elem_struct *elems, size_t count,
|
||||
bool inserted) {
|
||||
size_t *search_order = gpr_malloc(count * sizeof(*search_order));
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
search_order[i] = i;
|
||||
}
|
||||
for (size_t i = 0; i < count * 2; i++) {
|
||||
size_t a = (size_t)rand() % count;
|
||||
size_t b = (size_t)rand() % count;
|
||||
GPR_SWAP(size_t, search_order[a], search_order[b]);
|
||||
}
|
||||
elem_struct *out = NULL;
|
||||
for (size_t i = 0; out == NULL && i < count; i++) {
|
||||
if (elems[search_order[i]].inserted == inserted) {
|
||||
out = &elems[search_order[i]];
|
||||
}
|
||||
}
|
||||
gpr_free(search_order);
|
||||
return out;
|
||||
}
|
||||
|
||||
static void test2(void) {
|
||||
gpr_log(GPR_INFO, "test2");
|
||||
|
||||
grpc_timer_heap pq;
|
||||
|
||||
elem_struct elems[1000];
|
||||
size_t num_inserted = 0;
|
||||
|
||||
grpc_timer_heap_init(&pq);
|
||||
memset(elems, 0, sizeof(elems));
|
||||
|
||||
for (size_t round = 0; round < 10000; round++) {
|
||||
int r = rand() % 1000;
|
||||
if (r <= 550) {
|
||||
/* 55% of the time we try to add something */
|
||||
elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), false);
|
||||
if (el != NULL) {
|
||||
el->elem.deadline = random_deadline();
|
||||
grpc_timer_heap_add(&pq, &el->elem);
|
||||
el->inserted = true;
|
||||
num_inserted++;
|
||||
check_valid(&pq);
|
||||
}
|
||||
} else if (r <= 650) {
|
||||
/* 10% of the time we try to remove something */
|
||||
elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), true);
|
||||
if (el != NULL) {
|
||||
grpc_timer_heap_remove(&pq, &el->elem);
|
||||
el->inserted = false;
|
||||
num_inserted--;
|
||||
check_valid(&pq);
|
||||
}
|
||||
} else {
|
||||
/* the remaining times we pop */
|
||||
if (num_inserted > 0) {
|
||||
grpc_timer *top = grpc_timer_heap_top(&pq);
|
||||
grpc_timer_heap_pop(&pq);
|
||||
for (size_t i = 0; i < GPR_ARRAY_SIZE(elems); i++) {
|
||||
if (top == &elems[i].elem) {
|
||||
GPR_ASSERT(elems[i].inserted);
|
||||
elems[i].inserted = false;
|
||||
}
|
||||
}
|
||||
num_inserted--;
|
||||
check_valid(&pq);
|
||||
}
|
||||
}
|
||||
|
||||
if (num_inserted) {
|
||||
gpr_timespec *min_deadline = NULL;
|
||||
for (size_t i = 0; i < GPR_ARRAY_SIZE(elems); i++) {
|
||||
if (elems[i].inserted) {
|
||||
if (min_deadline == NULL) {
|
||||
min_deadline = &elems[i].elem.deadline;
|
||||
} else {
|
||||
if (gpr_time_cmp(elems[i].elem.deadline, *min_deadline) < 0) {
|
||||
min_deadline = &elems[i].elem.deadline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GPR_ASSERT(
|
||||
0 == gpr_time_cmp(grpc_timer_heap_top(&pq)->deadline, *min_deadline));
|
||||
}
|
||||
}
|
||||
|
||||
grpc_timer_heap_destroy(&pq);
|
||||
}
|
||||
|
||||
static void shrink_test(void) {
|
||||
gpr_log(GPR_INFO, "shrink_test");
|
||||
|
||||
grpc_timer_heap pq;
|
||||
size_t i;
|
||||
size_t expected_size;
|
||||
|
|
@ -274,6 +307,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
for (i = 0; i < 5; i++) {
|
||||
test1();
|
||||
test2();
|
||||
shrink_test();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -41,6 +41,8 @@
|
|||
#include <grpc/support/time.h>
|
||||
#include "test/core/util/test_config.h"
|
||||
|
||||
#define NUM_THREADS 300
|
||||
|
||||
struct test {
|
||||
gpr_mu mu;
|
||||
int n;
|
||||
|
|
@ -79,15 +81,14 @@ static void test_options(void) {
|
|||
static void test(void) {
|
||||
int i;
|
||||
gpr_thd_id thd;
|
||||
gpr_thd_id thds[1000];
|
||||
gpr_thd_id thds[NUM_THREADS];
|
||||
struct test t;
|
||||
int n = 1000;
|
||||
gpr_thd_options options = gpr_thd_options_default();
|
||||
gpr_mu_init(&t.mu);
|
||||
gpr_cv_init(&t.done_cv);
|
||||
t.n = n;
|
||||
t.n = NUM_THREADS;
|
||||
t.is_done = 0;
|
||||
for (i = 0; i != n; i++) {
|
||||
for (i = 0; i < NUM_THREADS; i++) {
|
||||
GPR_ASSERT(gpr_thd_new(&thd, &thd_body, &t, NULL));
|
||||
}
|
||||
gpr_mu_lock(&t.mu);
|
||||
|
|
@ -97,10 +98,10 @@ static void test(void) {
|
|||
gpr_mu_unlock(&t.mu);
|
||||
GPR_ASSERT(t.n == 0);
|
||||
gpr_thd_options_set_joinable(&options);
|
||||
for (i = 0; i < n; i++) {
|
||||
for (i = 0; i < NUM_THREADS; i++) {
|
||||
GPR_ASSERT(gpr_thd_new(&thds[i], &thd_body_joinable, NULL, &options));
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
for (i = 0; i < NUM_THREADS; i++) {
|
||||
gpr_thd_join(thds[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/thd.h>
|
||||
#include "test/core/util/test_config.h"
|
||||
|
||||
#define NUM_THREADS 100
|
||||
static grpc_channel* channels[NUM_THREADS];
|
||||
static grpc_completion_queue* queues[NUM_THREADS];
|
||||
|
||||
void create_loop_destroy(void* actually_an_int) {
|
||||
int thread_index = (int)(intptr_t)(actually_an_int);
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
grpc_completion_queue* cq = grpc_completion_queue_create(NULL);
|
||||
grpc_channel* chan = grpc_insecure_channel_create("localhost", NULL, NULL);
|
||||
|
||||
channels[thread_index] = chan;
|
||||
queues[thread_index] = cq;
|
||||
|
||||
for (int j = 0; j < 10; ++j) {
|
||||
gpr_timespec later_time = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10);
|
||||
grpc_connectivity_state state =
|
||||
grpc_channel_check_connectivity_state(chan, 1);
|
||||
grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL);
|
||||
GPR_ASSERT(grpc_completion_queue_next(cq,
|
||||
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
|
||||
NULL).type == GRPC_OP_COMPLETE);
|
||||
}
|
||||
grpc_channel_destroy(channels[thread_index]);
|
||||
grpc_completion_queue_destroy(queues[thread_index]);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
grpc_test_init(argc, argv);
|
||||
grpc_init();
|
||||
gpr_thd_id threads[NUM_THREADS];
|
||||
for (intptr_t i = 0; i < NUM_THREADS; ++i) {
|
||||
gpr_thd_options options = gpr_thd_options_default();
|
||||
gpr_thd_options_set_joinable(&options);
|
||||
gpr_thd_new(&threads[i], create_loop_destroy, (void*)i, &options);
|
||||
}
|
||||
for (int i = 0; i < NUM_THREADS; ++i) {
|
||||
gpr_thd_join(threads[i]);
|
||||
}
|
||||
grpc_shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* Copyright 2015-2016, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -61,35 +61,37 @@ typedef struct {
|
|||
of '#' will be replaced with a null character before processing. */
|
||||
const char *dns_names;
|
||||
|
||||
/* Comma separated list of IP SANs to match aggainst */
|
||||
const char *ip_names;
|
||||
} cert_name_test_entry;
|
||||
|
||||
/* Largely inspired from:
|
||||
chromium/src/net/cert/x509_certificate_unittest.cc.
|
||||
TODO(jboeuf) uncomment test cases as we fix tsi_ssl_peer_matches_name. */
|
||||
const cert_name_test_entry cert_name_test_entries[] = {
|
||||
{1, "foo.com", "foo.com", NULL},
|
||||
{1, "f", "f", NULL},
|
||||
{0, "h", "i", NULL},
|
||||
{1, "bar.foo.com", "*.foo.com", NULL},
|
||||
{1, "foo.com", "foo.com", NULL, NULL},
|
||||
{1, "f", "f", NULL, NULL},
|
||||
{0, "h", "i", NULL, NULL},
|
||||
{1, "bar.foo.com", "*.foo.com", NULL, NULL},
|
||||
{1, "www.test.fr", "common.name",
|
||||
"*.test.com,*.test.co.uk,*.test.de,*.test.fr"},
|
||||
"*.test.com,*.test.co.uk,*.test.de,*.test.fr", NULL},
|
||||
/*
|
||||
{1, "wwW.tESt.fr", "common.name", ",*.*,*.test.de,*.test.FR,www"},
|
||||
*/
|
||||
{0, "f.uk", ".uk", NULL},
|
||||
{0, "w.bar.foo.com", "?.bar.foo.com", NULL},
|
||||
{0, "www.foo.com", "(www|ftp).foo.com", NULL},
|
||||
{0, "www.foo.com", "www.foo.com#", NULL}, /* # = null char. */
|
||||
{0, "www.foo.com", "", "www.foo.com#*.foo.com,#,#"},
|
||||
{0, "www.house.example", "ww.house.example", NULL},
|
||||
{0, "test.org", "", "www.test.org,*.test.org,*.org"},
|
||||
{0, "w.bar.foo.com", "w*.bar.foo.com", NULL},
|
||||
{0, "www.bar.foo.com", "ww*ww.bar.foo.com", NULL},
|
||||
{0, "wwww.bar.foo.com", "ww*ww.bar.foo.com", NULL},
|
||||
{0, "wwww.bar.foo.com", "w*w.bar.foo.com", NULL},
|
||||
{0, "wwww.bar.foo.com", "w*w.bar.foo.c0m", NULL},
|
||||
{0, "WALLY.bar.foo.com", "wa*.bar.foo.com", NULL},
|
||||
{0, "wally.bar.foo.com", "*Ly.bar.foo.com", NULL},
|
||||
{0, "f.uk", ".uk", NULL, NULL},
|
||||
{0, "w.bar.foo.com", "?.bar.foo.com", NULL, NULL},
|
||||
{0, "www.foo.com", "(www|ftp).foo.com", NULL, NULL},
|
||||
{0, "www.foo.com", "www.foo.com#", NULL, NULL}, /* # = null char. */
|
||||
{0, "www.foo.com", "", "www.foo.com#*.foo.com,#,#", NULL},
|
||||
{0, "www.house.example", "ww.house.example", NULL, NULL},
|
||||
{0, "test.org", "", "www.test.org,*.test.org,*.org", NULL},
|
||||
{0, "w.bar.foo.com", "w*.bar.foo.com", NULL, NULL},
|
||||
{0, "www.bar.foo.com", "ww*ww.bar.foo.com", NULL, NULL},
|
||||
{0, "wwww.bar.foo.com", "ww*ww.bar.foo.com", NULL, NULL},
|
||||
{0, "wwww.bar.foo.com", "w*w.bar.foo.com", NULL, NULL},
|
||||
{0, "wwww.bar.foo.com", "w*w.bar.foo.c0m", NULL, NULL},
|
||||
{0, "WALLY.bar.foo.com", "wa*.bar.foo.com", NULL, NULL},
|
||||
{0, "wally.bar.foo.com", "*Ly.bar.foo.com", NULL, NULL},
|
||||
/*
|
||||
{1, "ww%57.foo.com", "", "www.foo.com"},
|
||||
{1, "www&.foo.com", "www%26.foo.com", NULL},
|
||||
|
|
@ -97,94 +99,108 @@ const cert_name_test_entry cert_name_test_entries[] = {
|
|||
|
||||
/* Common name must not be used if subject alternative name was provided. */
|
||||
{0, "www.test.co.jp", "www.test.co.jp",
|
||||
"*.test.de,*.jp,www.test.co.uk,www.*.co.jp"},
|
||||
"*.test.de,*.jp,www.test.co.uk,www.*.co.jp", NULL},
|
||||
{0, "www.bar.foo.com", "www.bar.foo.com",
|
||||
"*.foo.com,*.*.foo.com,*.*.bar.foo.com,*..bar.foo.com,"},
|
||||
"*.foo.com,*.*.foo.com,*.*.bar.foo.com,*..bar.foo.com,", NULL},
|
||||
|
||||
/* IDN tests */
|
||||
{1, "xn--poema-9qae5a.com.br", "xn--poema-9qae5a.com.br", NULL},
|
||||
{1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL},
|
||||
{1, "xn--poema-9qae5a.com.br", "xn--poema-9qae5a.com.br", NULL, NULL},
|
||||
{1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL, NULL},
|
||||
{0, "xn--poema-9qae5a.com.br", "",
|
||||
"*.xn--poema-9qae5a.com.br,"
|
||||
"xn--poema-*.com.br,"
|
||||
"xn--*-9qae5a.com.br,"
|
||||
"*--poema-9qae5a.com.br"},
|
||||
"*--poema-9qae5a.com.br",
|
||||
NULL},
|
||||
|
||||
/* The following are adapted from the examples quoted from
|
||||
http://tools.ietf.org/html/rfc6125#section-6.4.3
|
||||
(e.g., *.example.com would match foo.example.com but
|
||||
not bar.foo.example.com or example.com). */
|
||||
{1, "foo.example.com", "*.example.com", NULL},
|
||||
{0, "bar.foo.example.com", "*.example.com", NULL},
|
||||
{0, "example.com", "*.example.com", NULL},
|
||||
{1, "foo.example.com", "*.example.com", NULL, NULL},
|
||||
{0, "bar.foo.example.com", "*.example.com", NULL, NULL},
|
||||
{0, "example.com", "*.example.com", NULL, NULL},
|
||||
|
||||
/* Partial wildcards are disallowed, though RFC 2818 rules allow them.
|
||||
That is, forms such as baz*.example.net, *baz.example.net, and
|
||||
b*z.example.net should NOT match domains. Instead, the wildcard must
|
||||
always be the left-most label, and only a single label. */
|
||||
{0, "baz1.example.net", "baz*.example.net", NULL},
|
||||
{0, "foobaz.example.net", "*baz.example.net", NULL},
|
||||
{0, "buzz.example.net", "b*z.example.net", NULL},
|
||||
{0, "www.test.example.net", "www.*.example.net", NULL},
|
||||
{0, "baz1.example.net", "baz*.example.net", NULL, NULL},
|
||||
{0, "foobaz.example.net", "*baz.example.net", NULL, NULL},
|
||||
{0, "buzz.example.net", "b*z.example.net", NULL, NULL},
|
||||
{0, "www.test.example.net", "www.*.example.net", NULL, NULL},
|
||||
|
||||
/* Wildcards should not be valid for public registry controlled domains,
|
||||
and unknown/unrecognized domains, at least three domain components must
|
||||
be present. */
|
||||
{1, "www.test.example", "*.test.example", NULL},
|
||||
{1, "test.example.co.uk", "*.example.co.uk", NULL},
|
||||
{0, "test.example", "*.example", NULL},
|
||||
{1, "www.test.example", "*.test.example", NULL, NULL},
|
||||
{1, "test.example.co.uk", "*.example.co.uk", NULL, NULL},
|
||||
{0, "test.example", "*.example", NULL, NULL},
|
||||
/*
|
||||
{0, "example.co.uk", "*.co.uk", NULL},
|
||||
*/
|
||||
{0, "foo.com", "*.com", NULL},
|
||||
{0, "foo.us", "*.us", NULL},
|
||||
{0, "foo", "*", NULL},
|
||||
{0, "foo.com", "*.com", NULL, NULL},
|
||||
{0, "foo.us", "*.us", NULL, NULL},
|
||||
{0, "foo", "*", NULL, NULL},
|
||||
|
||||
/* IDN variants of wildcards and registry controlled domains. */
|
||||
{1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL},
|
||||
{1, "test.example.xn--mgbaam7a8h", "*.example.xn--mgbaam7a8h", NULL},
|
||||
{1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL, NULL},
|
||||
{1, "test.example.xn--mgbaam7a8h", "*.example.xn--mgbaam7a8h", NULL, NULL},
|
||||
/*
|
||||
{0, "xn--poema-9qae5a.com.br", "*.com.br", NULL},
|
||||
*/
|
||||
{0, "example.xn--mgbaam7a8h", "*.xn--mgbaam7a8h", NULL},
|
||||
{0, "example.xn--mgbaam7a8h", "*.xn--mgbaam7a8h", NULL, NULL},
|
||||
|
||||
/* Wildcards should be permissible for 'private' registry controlled
|
||||
domains. */
|
||||
{1, "www.appspot.com", "*.appspot.com", NULL},
|
||||
{1, "foo.s3.amazonaws.com", "*.s3.amazonaws.com", NULL},
|
||||
{1, "www.appspot.com", "*.appspot.com", NULL, NULL},
|
||||
{1, "foo.s3.amazonaws.com", "*.s3.amazonaws.com", NULL, NULL},
|
||||
|
||||
/* Multiple wildcards are not valid. */
|
||||
{0, "foo.example.com", "*.*.com", NULL},
|
||||
{0, "foo.bar.example.com", "*.bar.*.com", NULL},
|
||||
{0, "foo.example.com", "*.*.com", NULL, NULL},
|
||||
{0, "foo.bar.example.com", "*.bar.*.com", NULL, NULL},
|
||||
|
||||
/* Absolute vs relative DNS name tests. Although not explicitly specified
|
||||
in RFC 6125, absolute reference names (those ending in a .) should
|
||||
match either absolute or relative presented names. */
|
||||
{1, "foo.com", "foo.com.", NULL},
|
||||
{1, "foo.com.", "foo.com", NULL},
|
||||
{1, "foo.com.", "foo.com.", NULL},
|
||||
{1, "f", "f.", NULL},
|
||||
{1, "f.", "f", NULL},
|
||||
{1, "f.", "f.", NULL},
|
||||
{1, "www-3.bar.foo.com", "*.bar.foo.com.", NULL},
|
||||
{1, "www-3.bar.foo.com.", "*.bar.foo.com", NULL},
|
||||
{1, "www-3.bar.foo.com.", "*.bar.foo.com.", NULL},
|
||||
{0, ".", ".", NULL},
|
||||
{0, "example.com", "*.com.", NULL},
|
||||
{0, "example.com.", "*.com", NULL},
|
||||
{0, "example.com.", "*.com.", NULL},
|
||||
{0, "foo.", "*.", NULL},
|
||||
{0, "foo", "*.", NULL},
|
||||
{1, "foo.com", "foo.com.", NULL, NULL},
|
||||
{1, "foo.com.", "foo.com", NULL, NULL},
|
||||
{1, "foo.com.", "foo.com.", NULL, NULL},
|
||||
{1, "f", "f.", NULL, NULL},
|
||||
{1, "f.", "f", NULL, NULL},
|
||||
{1, "f.", "f.", NULL, NULL},
|
||||
{1, "www-3.bar.foo.com", "*.bar.foo.com.", NULL, NULL},
|
||||
{1, "www-3.bar.foo.com.", "*.bar.foo.com", NULL, NULL},
|
||||
{1, "www-3.bar.foo.com.", "*.bar.foo.com.", NULL, NULL},
|
||||
{0, ".", ".", NULL, NULL},
|
||||
{0, "example.com", "*.com.", NULL, NULL},
|
||||
{0, "example.com.", "*.com", NULL, NULL},
|
||||
{0, "example.com.", "*.com.", NULL, NULL},
|
||||
{0, "foo.", "*.", NULL, NULL},
|
||||
{0, "foo", "*.", NULL, NULL},
|
||||
/*
|
||||
{0, "foo.co.uk", "*.co.uk.", NULL},
|
||||
{0, "foo.co.uk.", "*.co.uk.", NULL},
|
||||
*/
|
||||
|
||||
/* An empty CN is OK. */
|
||||
{1, "test.foo.com", "", "test.foo.com"},
|
||||
{1, "test.foo.com", "", "test.foo.com", NULL},
|
||||
|
||||
/* An IP should not be used for the CN. */
|
||||
{0, "173.194.195.139", "173.194.195.139", NULL},
|
||||
{0, "173.194.195.139", "173.194.195.139", NULL, NULL},
|
||||
/* An IP can be used if the SAN IP is present */
|
||||
{1, "173.194.195.139", "foo.example.com", NULL, "173.194.195.139"},
|
||||
{0, "173.194.195.139", "foo.example.com", NULL, "8.8.8.8"},
|
||||
{0, "173.194.195.139", "foo.example.com", NULL, "8.8.8.8,8.8.4.4"},
|
||||
{1, "173.194.195.139", "foo.example.com", NULL, "8.8.8.8,173.194.195.139"},
|
||||
{0, "173.194.195.139", "foo.example.com", NULL, "173.194.195.13"},
|
||||
{0, "2001:db8:a0b:12f0::1", "foo.example.com", NULL, "173.194.195.13"},
|
||||
{1, "2001:db8:a0b:12f0::1", "foo.example.com", NULL,
|
||||
"2001:db8:a0b:12f0::1"},
|
||||
{0, "2001:db8:a0b:12f0::1", "foo.example.com", NULL,
|
||||
"2001:db8:a0b:12f0::2"},
|
||||
{1, "2001:db8:a0b:12f0::1", "foo.example.com", NULL,
|
||||
"2001:db8:a0b:12f0::2,2001:db8:a0b:12f0::1,8.8.8.8"},
|
||||
};
|
||||
|
||||
typedef struct name_list {
|
||||
|
|
@ -196,7 +212,7 @@ typedef struct {
|
|||
size_t name_count;
|
||||
char *buffer;
|
||||
name_list *names;
|
||||
} parsed_dns_names;
|
||||
} parsed_names;
|
||||
|
||||
name_list *name_list_add(const char *n) {
|
||||
name_list *result = gpr_malloc(sizeof(name_list));
|
||||
|
|
@ -205,18 +221,18 @@ name_list *name_list_add(const char *n) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static parsed_dns_names parse_dns_names(const char *dns_names_str) {
|
||||
parsed_dns_names result;
|
||||
static parsed_names parse_names(const char *names_str) {
|
||||
parsed_names result;
|
||||
name_list *current_nl;
|
||||
size_t i;
|
||||
memset(&result, 0, sizeof(parsed_dns_names));
|
||||
if (dns_names_str == 0) return result;
|
||||
memset(&result, 0, sizeof(parsed_names));
|
||||
if (names_str == 0) return result;
|
||||
result.name_count = 1;
|
||||
result.buffer = gpr_strdup(dns_names_str);
|
||||
result.buffer = gpr_strdup(names_str);
|
||||
result.names = name_list_add(result.buffer);
|
||||
current_nl = result.names;
|
||||
for (i = 0; i < strlen(dns_names_str); i++) {
|
||||
if (dns_names_str[i] == ',') {
|
||||
for (i = 0; i < strlen(names_str); i++) {
|
||||
if (names_str[i] == ',') {
|
||||
result.buffer[i] = '\0';
|
||||
result.name_count++;
|
||||
i++;
|
||||
|
|
@ -227,7 +243,7 @@ static parsed_dns_names parse_dns_names(const char *dns_names_str) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static void destruct_parsed_dns_names(parsed_dns_names *pdn) {
|
||||
static void destruct_parsed_names(parsed_names *pdn) {
|
||||
name_list *nl = pdn->names;
|
||||
if (pdn->buffer != NULL) gpr_free(pdn->buffer);
|
||||
while (nl != NULL) {
|
||||
|
|
@ -237,8 +253,8 @@ static void destruct_parsed_dns_names(parsed_dns_names *pdn) {
|
|||
}
|
||||
}
|
||||
|
||||
static char *processed_dns_name(const char *dns_name) {
|
||||
char *result = gpr_strdup(dns_name);
|
||||
static char *processed_name(const char *name) {
|
||||
char *result = gpr_strdup(name);
|
||||
size_t i;
|
||||
for (i = 0; i < strlen(result); i++) {
|
||||
if (result[i] == '#') {
|
||||
|
|
@ -253,31 +269,48 @@ static tsi_peer peer_from_cert_name_test_entry(
|
|||
size_t i;
|
||||
tsi_peer peer;
|
||||
name_list *nl;
|
||||
parsed_dns_names dns_entries = parse_dns_names(entry->dns_names);
|
||||
parsed_names dns_entries = parse_names(entry->dns_names);
|
||||
parsed_names ip_entries = parse_names(entry->ip_names);
|
||||
nl = dns_entries.names;
|
||||
GPR_ASSERT(tsi_construct_peer(1 + dns_entries.name_count, &peer) == TSI_OK);
|
||||
GPR_ASSERT(tsi_construct_peer(
|
||||
1 + dns_entries.name_count + ip_entries.name_count, &peer) ==
|
||||
TSI_OK);
|
||||
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
|
||||
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, entry->common_name,
|
||||
&peer.properties[0]) == TSI_OK);
|
||||
i = 1;
|
||||
while (nl != NULL) {
|
||||
char *processed = processed_dns_name(nl->name);
|
||||
char *processed = processed_name(nl->name);
|
||||
GPR_ASSERT(tsi_construct_string_peer_property(
|
||||
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, processed,
|
||||
strlen(nl->name), &peer.properties[i++]) == TSI_OK);
|
||||
nl = nl->next;
|
||||
gpr_free(processed);
|
||||
}
|
||||
destruct_parsed_dns_names(&dns_entries);
|
||||
|
||||
nl = ip_entries.names;
|
||||
while (nl != NULL) {
|
||||
char *processed = processed_name(nl->name);
|
||||
GPR_ASSERT(tsi_construct_string_peer_property(
|
||||
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, processed,
|
||||
strlen(nl->name), &peer.properties[i++]) == TSI_OK);
|
||||
nl = nl->next;
|
||||
gpr_free(processed);
|
||||
}
|
||||
destruct_parsed_names(&dns_entries);
|
||||
destruct_parsed_names(&ip_entries);
|
||||
return peer;
|
||||
}
|
||||
|
||||
char *cert_name_test_entry_to_string(const cert_name_test_entry *entry) {
|
||||
char *s;
|
||||
gpr_asprintf(
|
||||
&s, "{ success = %s, host_name = %s, common_name = %s, dns_names = %s}",
|
||||
entry->expected ? "true" : "false", entry->host_name, entry->common_name,
|
||||
entry->dns_names != NULL ? entry->dns_names : "");
|
||||
gpr_asprintf(&s,
|
||||
"{ success = %s, host_name = %s, common_name = %s, dns_names = "
|
||||
"%s, ip_names = %s}",
|
||||
entry->expected ? "true" : "false", entry->host_name,
|
||||
entry->common_name,
|
||||
entry->dns_names != NULL ? entry->dns_names : "",
|
||||
entry->ip_names != NULL ? entry->ip_names : "");
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ namespace testing {
|
|||
namespace {
|
||||
|
||||
void* tag(int i) { return (void*)(intptr_t)i; }
|
||||
int detag(void* p) { return static_cast<int>(reinterpret_cast<intptr_t>(p)); }
|
||||
|
||||
#ifdef GPR_POSIX_SOCKET
|
||||
static int maybe_assert_non_blocking_poll(struct pollfd* pfds, nfds_t nfds,
|
||||
|
|
@ -106,37 +107,50 @@ class PollingOverrider {
|
|||
class Verifier {
|
||||
public:
|
||||
explicit Verifier(bool spin) : spin_(spin) {}
|
||||
// Expect sets the expected ok value for a specific tag
|
||||
Verifier& Expect(int i, bool expect_ok) {
|
||||
expectations_[tag(i)] = expect_ok;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Next waits for 1 async tag to complete, checks its
|
||||
// expectations, and returns the tag
|
||||
int Next(CompletionQueue* cq, bool ignore_ok) {
|
||||
bool ok;
|
||||
void* got_tag;
|
||||
if (spin_) {
|
||||
for (;;) {
|
||||
auto r = cq->AsyncNext(&got_tag, &ok, gpr_time_0(GPR_CLOCK_REALTIME));
|
||||
if (r == CompletionQueue::TIMEOUT) continue;
|
||||
if (r == CompletionQueue::GOT_EVENT) break;
|
||||
gpr_log(GPR_ERROR, "unexpected result from AsyncNext");
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
EXPECT_TRUE(cq->Next(&got_tag, &ok));
|
||||
}
|
||||
auto it = expectations_.find(got_tag);
|
||||
EXPECT_TRUE(it != expectations_.end());
|
||||
if (!ignore_ok) {
|
||||
EXPECT_EQ(it->second, ok);
|
||||
}
|
||||
expectations_.erase(it);
|
||||
return detag(got_tag);
|
||||
}
|
||||
|
||||
// Verify keeps calling Next until all currently set
|
||||
// expected tags are complete
|
||||
void Verify(CompletionQueue* cq) { Verify(cq, false); }
|
||||
|
||||
// This version of Verify allows optionally ignoring the
|
||||
// outcome of the expectation
|
||||
void Verify(CompletionQueue* cq, bool ignore_ok) {
|
||||
GPR_ASSERT(!expectations_.empty());
|
||||
while (!expectations_.empty()) {
|
||||
bool ok;
|
||||
void* got_tag;
|
||||
if (spin_) {
|
||||
for (;;) {
|
||||
auto r = cq->AsyncNext(&got_tag, &ok, gpr_time_0(GPR_CLOCK_REALTIME));
|
||||
if (r == CompletionQueue::TIMEOUT) continue;
|
||||
if (r == CompletionQueue::GOT_EVENT) break;
|
||||
gpr_log(GPR_ERROR, "unexpected result from AsyncNext");
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
EXPECT_TRUE(cq->Next(&got_tag, &ok));
|
||||
}
|
||||
auto it = expectations_.find(got_tag);
|
||||
EXPECT_TRUE(it != expectations_.end());
|
||||
if (!ignore_ok) {
|
||||
EXPECT_EQ(it->second, ok);
|
||||
}
|
||||
expectations_.erase(it);
|
||||
Next(cq, ignore_ok);
|
||||
}
|
||||
}
|
||||
// This version of Verify stops after a certain deadline
|
||||
void Verify(CompletionQueue* cq,
|
||||
std::chrono::system_clock::time_point deadline) {
|
||||
if (expectations_.empty()) {
|
||||
|
|
@ -793,7 +807,8 @@ TEST_P(AsyncEnd2endTest, UnimplementedRpc) {
|
|||
}
|
||||
|
||||
// This class is for testing scenarios where RPCs are cancelled on the server
|
||||
// by calling ServerContext::TryCancel()
|
||||
// by calling ServerContext::TryCancel(). Server uses AsyncNotifyWhenDone
|
||||
// API to check for cancellation
|
||||
class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
||||
protected:
|
||||
typedef enum {
|
||||
|
|
@ -803,13 +818,6 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
CANCEL_AFTER_PROCESSING
|
||||
} ServerTryCancelRequestPhase;
|
||||
|
||||
void ServerTryCancel(ServerContext* context) {
|
||||
EXPECT_FALSE(context->IsCancelled());
|
||||
context->TryCancel();
|
||||
gpr_log(GPR_INFO, "Server called TryCancel()");
|
||||
EXPECT_TRUE(context->IsCancelled());
|
||||
}
|
||||
|
||||
// Helper for testing client-streaming RPCs which are cancelled on the server.
|
||||
// Depending on the value of server_try_cancel parameter, this will test one
|
||||
// of the following three scenarios:
|
||||
|
|
@ -843,6 +851,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
|
||||
// On the server, request to be notified of 'RequestStream' calls
|
||||
// and receive the 'RequestStream' call just made by the client
|
||||
srv_ctx.AsyncNotifyWhenDone(tag(11));
|
||||
service_.RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
|
||||
tag(2));
|
||||
Verifier(GetParam()).Expect(2, true).Verify(cq_.get());
|
||||
|
|
@ -858,9 +867,12 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
|
||||
bool expected_server_cq_result = true;
|
||||
bool ignore_cq_result = false;
|
||||
bool want_done_tag = false;
|
||||
|
||||
if (server_try_cancel == CANCEL_BEFORE_PROCESSING) {
|
||||
ServerTryCancel(&srv_ctx);
|
||||
srv_ctx.TryCancel();
|
||||
Verifier(GetParam()).Expect(11, true).Verify(cq_.get());
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
|
||||
// Since cancellation is done before server reads any results, we know
|
||||
// for sure that all cq results will return false from this point forward
|
||||
|
|
@ -868,22 +880,39 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
}
|
||||
|
||||
std::thread* server_try_cancel_thd = NULL;
|
||||
|
||||
auto verif = Verifier(GetParam());
|
||||
|
||||
if (server_try_cancel == CANCEL_DURING_PROCESSING) {
|
||||
server_try_cancel_thd = new std::thread(
|
||||
&AsyncEnd2endServerTryCancelTest::ServerTryCancel, this, &srv_ctx);
|
||||
server_try_cancel_thd =
|
||||
new std::thread(&ServerContext::TryCancel, &srv_ctx);
|
||||
// Server will cancel the RPC in a parallel thread while reading the
|
||||
// requests from the client. Since the cancellation can happen at anytime,
|
||||
// some of the cq results (i.e those until cancellation) might be true but
|
||||
// its non deterministic. So better to ignore the cq results
|
||||
ignore_cq_result = true;
|
||||
// Expect that we might possibly see the done tag that
|
||||
// indicates cancellation completion in this case
|
||||
want_done_tag = true;
|
||||
verif.Expect(11, true);
|
||||
}
|
||||
|
||||
// Server reads 3 messages (tags 6, 7 and 8)
|
||||
// But if want_done_tag is true, we might also see tag 11
|
||||
for (int tag_idx = 6; tag_idx <= 8; tag_idx++) {
|
||||
srv_stream.Read(&recv_request, tag(tag_idx));
|
||||
Verifier(GetParam())
|
||||
.Expect(tag_idx, expected_server_cq_result)
|
||||
.Verify(cq_.get(), ignore_cq_result);
|
||||
// Note that we'll add something to the verifier and verify that
|
||||
// something was seen, but it might be tag 11 and not what we
|
||||
// just added
|
||||
int got_tag = verif.Expect(tag_idx, expected_server_cq_result)
|
||||
.Next(cq_.get(), ignore_cq_result);
|
||||
GPR_ASSERT((got_tag == tag_idx) || (got_tag == 11 && want_done_tag));
|
||||
if (got_tag == 11) {
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
// Now get the other entry that we were waiting on
|
||||
EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), tag_idx);
|
||||
}
|
||||
}
|
||||
|
||||
if (server_try_cancel_thd != NULL) {
|
||||
|
|
@ -892,7 +921,15 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
}
|
||||
|
||||
if (server_try_cancel == CANCEL_AFTER_PROCESSING) {
|
||||
ServerTryCancel(&srv_ctx);
|
||||
srv_ctx.TryCancel();
|
||||
want_done_tag = true;
|
||||
verif.Expect(11, true);
|
||||
}
|
||||
|
||||
if (want_done_tag) {
|
||||
verif.Verify(cq_.get());
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
}
|
||||
|
||||
// The RPC has been cancelled at this point for sure (i.e irrespective of
|
||||
|
|
@ -945,6 +982,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
Verifier(GetParam()).Expect(1, true).Verify(cq_.get());
|
||||
// On the server, request to be notified of 'ResponseStream' calls and
|
||||
// receive the call just made by the client
|
||||
srv_ctx.AsyncNotifyWhenDone(tag(11));
|
||||
service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
|
||||
cq_.get(), cq_.get(), tag(2));
|
||||
Verifier(GetParam()).Expect(2, true).Verify(cq_.get());
|
||||
|
|
@ -952,9 +990,12 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
|
||||
bool expected_cq_result = true;
|
||||
bool ignore_cq_result = false;
|
||||
bool want_done_tag = false;
|
||||
|
||||
if (server_try_cancel == CANCEL_BEFORE_PROCESSING) {
|
||||
ServerTryCancel(&srv_ctx);
|
||||
srv_ctx.TryCancel();
|
||||
Verifier(GetParam()).Expect(11, true).Verify(cq_.get());
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
|
||||
// We know for sure that all cq results will be false from this point
|
||||
// since the server cancelled the RPC
|
||||
|
|
@ -962,24 +1003,41 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
}
|
||||
|
||||
std::thread* server_try_cancel_thd = NULL;
|
||||
|
||||
auto verif = Verifier(GetParam());
|
||||
|
||||
if (server_try_cancel == CANCEL_DURING_PROCESSING) {
|
||||
server_try_cancel_thd = new std::thread(
|
||||
&AsyncEnd2endServerTryCancelTest::ServerTryCancel, this, &srv_ctx);
|
||||
server_try_cancel_thd =
|
||||
new std::thread(&ServerContext::TryCancel, &srv_ctx);
|
||||
|
||||
// Server will cancel the RPC in a parallel thread while writing responses
|
||||
// to the client. Since the cancellation can happen at anytime, some of
|
||||
// the cq results (i.e those until cancellation) might be true but it is
|
||||
// non deterministic. So better to ignore the cq results
|
||||
ignore_cq_result = true;
|
||||
// Expect that we might possibly see the done tag that
|
||||
// indicates cancellation completion in this case
|
||||
want_done_tag = true;
|
||||
verif.Expect(11, true);
|
||||
}
|
||||
|
||||
// Server sends three messages (tags 3, 4 and 5)
|
||||
// But if want_done tag is true, we might also see tag 11
|
||||
for (int tag_idx = 3; tag_idx <= 5; tag_idx++) {
|
||||
send_response.set_message("Pong " + std::to_string(tag_idx));
|
||||
srv_stream.Write(send_response, tag(tag_idx));
|
||||
Verifier(GetParam())
|
||||
.Expect(tag_idx, expected_cq_result)
|
||||
.Verify(cq_.get(), ignore_cq_result);
|
||||
// Note that we'll add something to the verifier and verify that
|
||||
// something was seen, but it might be tag 11 and not what we
|
||||
// just added
|
||||
int got_tag = verif.Expect(tag_idx, expected_cq_result)
|
||||
.Next(cq_.get(), ignore_cq_result);
|
||||
GPR_ASSERT((got_tag == tag_idx) || (got_tag == 11 && want_done_tag));
|
||||
if (got_tag == 11) {
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
// Now get the other entry that we were waiting on
|
||||
EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), tag_idx);
|
||||
}
|
||||
}
|
||||
|
||||
if (server_try_cancel_thd != NULL) {
|
||||
|
|
@ -988,13 +1046,21 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
}
|
||||
|
||||
if (server_try_cancel == CANCEL_AFTER_PROCESSING) {
|
||||
ServerTryCancel(&srv_ctx);
|
||||
srv_ctx.TryCancel();
|
||||
want_done_tag = true;
|
||||
verif.Expect(11, true);
|
||||
|
||||
// Client reads may fail bacause it is notified that the stream is
|
||||
// cancelled.
|
||||
ignore_cq_result = true;
|
||||
}
|
||||
|
||||
if (want_done_tag) {
|
||||
verif.Verify(cq_.get());
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
}
|
||||
|
||||
// Client attemts to read the three messages from the server
|
||||
for (int tag_idx = 6; tag_idx <= 8; tag_idx++) {
|
||||
cli_stream->Read(&recv_response, tag(tag_idx));
|
||||
|
|
@ -1052,6 +1118,7 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
|
||||
// On the server, request to be notified of the 'BidiStream' call and
|
||||
// receive the call just made by the client
|
||||
srv_ctx.AsyncNotifyWhenDone(tag(11));
|
||||
service_.RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
|
||||
tag(2));
|
||||
Verifier(GetParam()).Expect(2, true).Verify(cq_.get());
|
||||
|
|
@ -1063,9 +1130,12 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
|
||||
bool expected_cq_result = true;
|
||||
bool ignore_cq_result = false;
|
||||
bool want_done_tag = false;
|
||||
|
||||
if (server_try_cancel == CANCEL_BEFORE_PROCESSING) {
|
||||
ServerTryCancel(&srv_ctx);
|
||||
srv_ctx.TryCancel();
|
||||
Verifier(GetParam()).Expect(11, true).Verify(cq_.get());
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
|
||||
// We know for sure that all cq results will be false from this point
|
||||
// since the server cancelled the RPC
|
||||
|
|
@ -1073,42 +1143,84 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
}
|
||||
|
||||
std::thread* server_try_cancel_thd = NULL;
|
||||
|
||||
auto verif = Verifier(GetParam());
|
||||
|
||||
if (server_try_cancel == CANCEL_DURING_PROCESSING) {
|
||||
server_try_cancel_thd = new std::thread(
|
||||
&AsyncEnd2endServerTryCancelTest::ServerTryCancel, this, &srv_ctx);
|
||||
server_try_cancel_thd =
|
||||
new std::thread(&ServerContext::TryCancel, &srv_ctx);
|
||||
|
||||
// Since server is going to cancel the RPC in a parallel thread, some of
|
||||
// the cq results (i.e those until the cancellation) might be true. Since
|
||||
// that number is non-deterministic, it is better to ignore the cq results
|
||||
ignore_cq_result = true;
|
||||
// Expect that we might possibly see the done tag that
|
||||
// indicates cancellation completion in this case
|
||||
want_done_tag = true;
|
||||
verif.Expect(11, true);
|
||||
}
|
||||
|
||||
int got_tag;
|
||||
srv_stream.Read(&recv_request, tag(4));
|
||||
Verifier(GetParam())
|
||||
.Expect(4, expected_cq_result)
|
||||
.Verify(cq_.get(), ignore_cq_result);
|
||||
verif.Expect(4, expected_cq_result);
|
||||
got_tag = verif.Next(cq_.get(), ignore_cq_result);
|
||||
GPR_ASSERT((got_tag == 4) || (got_tag == 11 && want_done_tag));
|
||||
if (got_tag == 11) {
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
// Now get the other entry that we were waiting on
|
||||
EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 4);
|
||||
}
|
||||
|
||||
send_response.set_message("Pong");
|
||||
srv_stream.Write(send_response, tag(5));
|
||||
Verifier(GetParam())
|
||||
.Expect(5, expected_cq_result)
|
||||
.Verify(cq_.get(), ignore_cq_result);
|
||||
verif.Expect(5, expected_cq_result);
|
||||
got_tag = verif.Next(cq_.get(), ignore_cq_result);
|
||||
GPR_ASSERT((got_tag == 5) || (got_tag == 11 && want_done_tag));
|
||||
if (got_tag == 11) {
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
// Now get the other entry that we were waiting on
|
||||
EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 5);
|
||||
}
|
||||
|
||||
cli_stream->Read(&recv_response, tag(6));
|
||||
Verifier(GetParam())
|
||||
.Expect(6, expected_cq_result)
|
||||
.Verify(cq_.get(), ignore_cq_result);
|
||||
verif.Expect(6, expected_cq_result);
|
||||
got_tag = verif.Next(cq_.get(), ignore_cq_result);
|
||||
GPR_ASSERT((got_tag == 6) || (got_tag == 11 && want_done_tag));
|
||||
if (got_tag == 11) {
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
// Now get the other entry that we were waiting on
|
||||
EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 6);
|
||||
}
|
||||
|
||||
// This is expected to succeed in all cases
|
||||
cli_stream->WritesDone(tag(7));
|
||||
Verifier(GetParam()).Expect(7, true).Verify(cq_.get());
|
||||
verif.Expect(7, true);
|
||||
got_tag = verif.Next(cq_.get(), ignore_cq_result);
|
||||
GPR_ASSERT((got_tag == 7) || (got_tag == 11 && want_done_tag));
|
||||
if (got_tag == 11) {
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
// Now get the other entry that we were waiting on
|
||||
EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 7);
|
||||
}
|
||||
|
||||
// This is expected to fail in all cases i.e for all values of
|
||||
// server_try_cancel. This is because at this point, either there are no
|
||||
// more msgs from the client (because client called WritesDone) or the RPC
|
||||
// is cancelled on the server
|
||||
srv_stream.Read(&recv_request, tag(8));
|
||||
Verifier(GetParam()).Expect(8, false).Verify(cq_.get());
|
||||
verif.Expect(8, false);
|
||||
got_tag = verif.Next(cq_.get(), ignore_cq_result);
|
||||
GPR_ASSERT((got_tag == 8) || (got_tag == 11 && want_done_tag));
|
||||
if (got_tag == 11) {
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
// Now get the other entry that we were waiting on
|
||||
EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 8);
|
||||
}
|
||||
|
||||
if (server_try_cancel_thd != NULL) {
|
||||
server_try_cancel_thd->join();
|
||||
|
|
@ -1116,7 +1228,15 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
|
|||
}
|
||||
|
||||
if (server_try_cancel == CANCEL_AFTER_PROCESSING) {
|
||||
ServerTryCancel(&srv_ctx);
|
||||
srv_ctx.TryCancel();
|
||||
want_done_tag = true;
|
||||
verif.Expect(11, true);
|
||||
}
|
||||
|
||||
if (want_done_tag) {
|
||||
verif.Verify(cq_.get());
|
||||
EXPECT_TRUE(srv_ctx.IsCancelled());
|
||||
want_done_tag = false;
|
||||
}
|
||||
|
||||
// The RPC has been cancelled at this point for sure (i.e irrespective of
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
|
||||
using grpc::testing::EchoRequest;
|
||||
using grpc::testing::EchoResponse;
|
||||
using grpc::testing::kTlsCredentialsType;
|
||||
using std::chrono::system_clock;
|
||||
|
||||
namespace grpc {
|
||||
|
|
@ -1194,6 +1195,8 @@ TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorSuccess) {
|
|||
request.mutable_param()->set_echo_metadata(true);
|
||||
request.mutable_param()->set_expected_client_identity(
|
||||
TestAuthMetadataProcessor::kGoodGuy);
|
||||
request.mutable_param()->set_expected_transport_security_type(
|
||||
GetParam().credentials_type);
|
||||
|
||||
Status s = stub_->Echo(&context, request, &response);
|
||||
EXPECT_EQ(request.message(), response.message());
|
||||
|
|
@ -1301,6 +1304,8 @@ TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) {
|
|||
request.mutable_param()->set_echo_metadata(true);
|
||||
request.mutable_param()->set_expected_client_identity(
|
||||
TestAuthMetadataProcessor::kGoodGuy);
|
||||
request.mutable_param()->set_expected_transport_security_type(
|
||||
GetParam().credentials_type);
|
||||
|
||||
Status s = stub_->Echo(&context, request, &response);
|
||||
EXPECT_EQ(request.message(), response.message());
|
||||
|
|
@ -1349,25 +1354,30 @@ TEST_P(SecureEnd2endTest, ClientAuthContext) {
|
|||
EchoRequest request;
|
||||
EchoResponse response;
|
||||
request.set_message("Hello");
|
||||
request.mutable_param()->set_check_auth_context(true);
|
||||
|
||||
request.mutable_param()->set_check_auth_context(GetParam().credentials_type ==
|
||||
kTlsCredentialsType);
|
||||
request.mutable_param()->set_expected_transport_security_type(
|
||||
GetParam().credentials_type);
|
||||
ClientContext context;
|
||||
Status s = stub_->Echo(&context, request, &response);
|
||||
EXPECT_EQ(response.message(), request.message());
|
||||
EXPECT_TRUE(s.ok());
|
||||
|
||||
std::shared_ptr<const AuthContext> auth_ctx = context.auth_context();
|
||||
std::vector<grpc::string_ref> ssl =
|
||||
std::vector<grpc::string_ref> tst =
|
||||
auth_ctx->FindPropertyValues("transport_security_type");
|
||||
EXPECT_EQ(1u, ssl.size());
|
||||
EXPECT_EQ("ssl", ToString(ssl[0]));
|
||||
EXPECT_EQ("x509_subject_alternative_name",
|
||||
auth_ctx->GetPeerIdentityPropertyName());
|
||||
EXPECT_EQ(3u, auth_ctx->GetPeerIdentity().size());
|
||||
EXPECT_EQ("*.test.google.fr", ToString(auth_ctx->GetPeerIdentity()[0]));
|
||||
EXPECT_EQ("waterzooi.test.google.be",
|
||||
ToString(auth_ctx->GetPeerIdentity()[1]));
|
||||
EXPECT_EQ("*.test.youtube.com", ToString(auth_ctx->GetPeerIdentity()[2]));
|
||||
EXPECT_EQ(1u, tst.size());
|
||||
EXPECT_EQ(GetParam().credentials_type, ToString(tst[0]));
|
||||
if (GetParam().credentials_type == kTlsCredentialsType) {
|
||||
EXPECT_EQ("x509_subject_alternative_name",
|
||||
auth_ctx->GetPeerIdentityPropertyName());
|
||||
EXPECT_EQ(4u, auth_ctx->GetPeerIdentity().size());
|
||||
EXPECT_EQ("*.test.google.fr", ToString(auth_ctx->GetPeerIdentity()[0]));
|
||||
EXPECT_EQ("waterzooi.test.google.be",
|
||||
ToString(auth_ctx->GetPeerIdentity()[1]));
|
||||
EXPECT_EQ("*.test.youtube.com", ToString(auth_ctx->GetPeerIdentity()[2]));
|
||||
EXPECT_EQ("192.168.1.3", ToString(auth_ctx->GetPeerIdentity()[3]));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<TestScenario> CreateTestScenarios(bool use_proxy,
|
||||
|
|
|
|||
|
|
@ -62,14 +62,16 @@ void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request,
|
|||
}
|
||||
}
|
||||
|
||||
void CheckServerAuthContext(const ServerContext* context,
|
||||
const grpc::string& expected_client_identity) {
|
||||
void CheckServerAuthContext(
|
||||
const ServerContext* context,
|
||||
const grpc::string& expected_transport_security_type,
|
||||
const grpc::string& expected_client_identity) {
|
||||
std::shared_ptr<const AuthContext> auth_ctx = context->auth_context();
|
||||
std::vector<grpc::string_ref> ssl =
|
||||
std::vector<grpc::string_ref> tst =
|
||||
auth_ctx->FindPropertyValues("transport_security_type");
|
||||
EXPECT_EQ(1u, ssl.size());
|
||||
EXPECT_EQ("ssl", ToString(ssl[0]));
|
||||
if (expected_client_identity.length() == 0) {
|
||||
EXPECT_EQ(1u, tst.size());
|
||||
EXPECT_EQ(expected_transport_security_type, ToString(tst[0]));
|
||||
if (expected_client_identity.empty()) {
|
||||
EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty());
|
||||
EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty());
|
||||
EXPECT_FALSE(auth_ctx->IsPeerAuthenticated());
|
||||
|
|
@ -139,6 +141,7 @@ Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request,
|
|||
(request->param().expected_client_identity().length() > 0 ||
|
||||
request->param().check_auth_context())) {
|
||||
CheckServerAuthContext(context,
|
||||
request->param().expected_transport_security_type(),
|
||||
request->param().expected_client_identity());
|
||||
}
|
||||
if (request->has_param() && request->param().response_message_length() > 0) {
|
||||
|
|
|
|||
|
|
@ -123,15 +123,13 @@ class Client {
|
|||
if (reset) {
|
||||
Histogram* to_merge = new Histogram[threads_.size()];
|
||||
for (size_t i = 0; i < threads_.size(); i++) {
|
||||
threads_[i]->BeginSwap(&to_merge[i]);
|
||||
}
|
||||
std::unique_ptr<UsageTimer> timer(new UsageTimer);
|
||||
timer_.swap(timer);
|
||||
for (size_t i = 0; i < threads_.size(); i++) {
|
||||
threads_[i]->EndSwap();
|
||||
threads_[i]->Swap(&to_merge[i]);
|
||||
latencies.Merge(to_merge[i]);
|
||||
}
|
||||
delete[] to_merge;
|
||||
|
||||
std::unique_ptr<UsageTimer> timer(new UsageTimer);
|
||||
timer_.swap(timer);
|
||||
timer_result = timer->Mark();
|
||||
} else {
|
||||
// merge snapshots of each thread histogram
|
||||
|
|
@ -227,7 +225,6 @@ class Client {
|
|||
public:
|
||||
Thread(Client* client, size_t idx)
|
||||
: done_(false),
|
||||
new_stats_(nullptr),
|
||||
client_(client),
|
||||
idx_(idx),
|
||||
impl_(&Thread::ThreadFunc, this) {}
|
||||
|
|
@ -240,16 +237,9 @@ class Client {
|
|||
impl_.join();
|
||||
}
|
||||
|
||||
void BeginSwap(Histogram* n) {
|
||||
void Swap(Histogram* n) {
|
||||
std::lock_guard<std::mutex> g(mu_);
|
||||
new_stats_ = n;
|
||||
}
|
||||
|
||||
void EndSwap() {
|
||||
std::unique_lock<std::mutex> g(mu_);
|
||||
while (new_stats_ != nullptr) {
|
||||
cv_.wait(g);
|
||||
};
|
||||
n->Swap(&histogram_);
|
||||
}
|
||||
|
||||
void MergeStatsInto(Histogram* hist) {
|
||||
|
|
@ -263,10 +253,11 @@ class Client {
|
|||
|
||||
void ThreadFunc() {
|
||||
for (;;) {
|
||||
// lock since the thread should only be doing one thing at a time
|
||||
std::lock_guard<std::mutex> g(mu_);
|
||||
// run the loop body
|
||||
const bool thread_still_ok = client_->ThreadFunc(&histogram_, idx_);
|
||||
// lock, see if we're done
|
||||
std::lock_guard<std::mutex> g(mu_);
|
||||
// see if we're done
|
||||
if (!thread_still_ok) {
|
||||
gpr_log(GPR_ERROR, "Finishing client thread due to RPC error");
|
||||
done_ = true;
|
||||
|
|
@ -274,19 +265,11 @@ class Client {
|
|||
if (done_) {
|
||||
return;
|
||||
}
|
||||
// check if we're resetting stats, swap out the histogram if so
|
||||
if (new_stats_) {
|
||||
new_stats_->Swap(&histogram_);
|
||||
new_stats_ = nullptr;
|
||||
cv_.notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::mutex mu_;
|
||||
std::condition_variable cv_;
|
||||
bool done_;
|
||||
Histogram* new_stats_;
|
||||
Histogram histogram_;
|
||||
Client* client_;
|
||||
const size_t idx_;
|
||||
|
|
|
|||
|
|
@ -348,19 +348,10 @@ std::unique_ptr<ScenarioResult> RunScenario(
|
|||
std::unique_ptr<ScenarioResult> result(new ScenarioResult);
|
||||
result->client_config = result_client_config;
|
||||
result->server_config = result_server_config;
|
||||
gpr_log(GPR_INFO, "Finishing");
|
||||
for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
|
||||
GPR_ASSERT(server->stream->Write(server_mark));
|
||||
}
|
||||
gpr_log(GPR_INFO, "Finishing clients");
|
||||
for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
|
||||
GPR_ASSERT(client->stream->Write(client_mark));
|
||||
}
|
||||
for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
|
||||
GPR_ASSERT(server->stream->Read(&server_status));
|
||||
const auto& stats = server_status.stats();
|
||||
result->server_resources.emplace_back(
|
||||
stats.time_elapsed(), stats.time_user(), stats.time_system(),
|
||||
server_status.cores());
|
||||
GPR_ASSERT(client->stream->WritesDone());
|
||||
}
|
||||
for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
|
||||
GPR_ASSERT(client->stream->Read(&client_status));
|
||||
|
|
@ -368,17 +359,30 @@ std::unique_ptr<ScenarioResult> RunScenario(
|
|||
result->latencies.MergeProto(stats.latencies());
|
||||
result->client_resources.emplace_back(
|
||||
stats.time_elapsed(), stats.time_user(), stats.time_system(), -1);
|
||||
GPR_ASSERT(!client->stream->Read(&client_status));
|
||||
}
|
||||
|
||||
for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
|
||||
GPR_ASSERT(client->stream->WritesDone());
|
||||
GPR_ASSERT(client->stream->Finish().ok());
|
||||
}
|
||||
delete[] clients;
|
||||
|
||||
gpr_log(GPR_INFO, "Finishing servers");
|
||||
for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
|
||||
GPR_ASSERT(server->stream->Write(server_mark));
|
||||
GPR_ASSERT(server->stream->WritesDone());
|
||||
}
|
||||
for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
|
||||
GPR_ASSERT(server->stream->Read(&server_status));
|
||||
const auto& stats = server_status.stats();
|
||||
result->server_resources.emplace_back(
|
||||
stats.time_elapsed(), stats.time_user(), stats.time_system(),
|
||||
server_status.cores());
|
||||
GPR_ASSERT(!server->stream->Read(&server_status));
|
||||
}
|
||||
for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
|
||||
GPR_ASSERT(server->stream->Finish().ok());
|
||||
}
|
||||
delete[] clients;
|
||||
|
||||
delete[] servers;
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,10 @@ namespace grpc {
|
|||
namespace testing {
|
||||
|
||||
const char kInsecureCredentialsType[] = "INSECURE_CREDENTIALS";
|
||||
const char kTlsCredentialsType[] = "TLS_CREDENTIALS";
|
||||
|
||||
// For real credentials, like tls/ssl, this name should match the AuthContext
|
||||
// property "transport_security_type".
|
||||
const char kTlsCredentialsType[] = "ssl";
|
||||
|
||||
// Provide test credentials of a particular type.
|
||||
class CredentialTypeProvider {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python2.7
|
||||
# Copyright 2015, Google Inc.
|
||||
# Copyright 2015-2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -51,29 +51,35 @@ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|||
PROJECT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, '..', '..', '..'))
|
||||
|
||||
CONFIG = args.config
|
||||
SETUP_PATH = os.path.join(PROJECT_ROOT, 'src/python/grpcio/setup.py')
|
||||
DOC_PATH = os.path.join(PROJECT_ROOT, 'src/python/grpcio/doc/build')
|
||||
SETUP_PATH = os.path.join(PROJECT_ROOT, 'setup.py')
|
||||
REQUIREMENTS_PATH = os.path.join(PROJECT_ROOT, 'requirements.txt')
|
||||
DOC_PATH = os.path.join(PROJECT_ROOT, 'doc/build')
|
||||
INCLUDE_PATH = os.path.join(PROJECT_ROOT, 'include')
|
||||
LIBRARY_PATH = os.path.join(PROJECT_ROOT, 'libs/{}'.format(CONFIG))
|
||||
VIRTUALENV_DIR = os.path.join(SCRIPT_DIR, 'distrib_virtualenv')
|
||||
VIRTUALENV_PYTHON_PATH = os.path.join(VIRTUALENV_DIR, 'bin', 'python')
|
||||
VIRTUALENV_PIP_PATH = os.path.join(VIRTUALENV_DIR, 'bin', 'pip')
|
||||
|
||||
environment = os.environ.copy()
|
||||
environment.update({
|
||||
'CONFIG': CONFIG,
|
||||
'CFLAGS': '-I{}'.format(INCLUDE_PATH),
|
||||
'LDFLAGS': '-L{}'.format(LIBRARY_PATH),
|
||||
'LD_LIBRARY_PATH': LIBRARY_PATH
|
||||
'LD_LIBRARY_PATH': LIBRARY_PATH,
|
||||
'GRPC_PYTHON_BUILD_WITH_CYTHON': '1',
|
||||
})
|
||||
|
||||
subprocess_arguments_list = [
|
||||
{'args': ['make'], 'cwd': PROJECT_ROOT},
|
||||
{'args': ['virtualenv', VIRTUALENV_DIR], 'env': environment},
|
||||
{'args': [VIRTUALENV_PIP_PATH, 'install', '-r', REQUIREMENTS_PATH],
|
||||
'env': environment},
|
||||
{'args': [VIRTUALENV_PYTHON_PATH, SETUP_PATH, 'build'], 'env': environment},
|
||||
{'args': [VIRTUALENV_PYTHON_PATH, SETUP_PATH, 'doc'], 'env': environment},
|
||||
]
|
||||
|
||||
for subprocess_arguments in subprocess_arguments_list:
|
||||
print('Running command: {}'.format(subprocess_arguments['args']))
|
||||
subprocess.check_call(**subprocess_arguments)
|
||||
|
||||
if args.submit:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
# Copyright 2015-2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
FROM ubuntu:14.04
|
||||
|
||||
# Install Git and basic packages.
|
||||
RUN apt-get update && apt-get install -y \
|
||||
autoconf \
|
||||
autotools-dev \
|
||||
build-essential \
|
||||
bzip2 \
|
||||
ccache \
|
||||
curl \
|
||||
gcc \
|
||||
gcc-multilib \
|
||||
git \
|
||||
golang \
|
||||
gyp \
|
||||
lcov \
|
||||
libc6 \
|
||||
libc6-dbg \
|
||||
libc6-dev \
|
||||
libgtest-dev \
|
||||
libtool \
|
||||
make \
|
||||
perl \
|
||||
strace \
|
||||
python-dev \
|
||||
python-setuptools \
|
||||
python-yaml \
|
||||
telnet \
|
||||
unzip \
|
||||
wget \
|
||||
zip && apt-get clean
|
||||
|
||||
#================
|
||||
# Build profiling
|
||||
RUN apt-get update && apt-get install -y time && apt-get clean
|
||||
|
||||
#=================
|
||||
# C++ dependencies
|
||||
RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
|
||||
|
||||
# Prepare ccache
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/g++
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/cc
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/c++
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/clang
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
|
||||
|
||||
#======================
|
||||
# Zookeeper dependencies
|
||||
# TODO(jtattermusch): is zookeeper still needed?
|
||||
RUN apt-get install -y libzookeeper-mt-dev
|
||||
|
||||
RUN mkdir /var/local/jenkins
|
||||
|
||||
# Define the default command.
|
||||
CMD ["bash"]
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
# Copyright 2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
FROM debian:jessie
|
||||
|
||||
# Install Git and basic packages.
|
||||
RUN apt-get update && apt-get install -y \
|
||||
autoconf \
|
||||
autotools-dev \
|
||||
build-essential \
|
||||
bzip2 \
|
||||
ccache \
|
||||
curl \
|
||||
gcc \
|
||||
gcc-multilib \
|
||||
git \
|
||||
golang \
|
||||
gyp \
|
||||
lcov \
|
||||
libc6 \
|
||||
libc6-dbg \
|
||||
libc6-dev \
|
||||
libgtest-dev \
|
||||
libtool \
|
||||
make \
|
||||
perl \
|
||||
strace \
|
||||
python-dev \
|
||||
python-setuptools \
|
||||
python-yaml \
|
||||
telnet \
|
||||
unzip \
|
||||
wget \
|
||||
zip && apt-get clean
|
||||
|
||||
#================
|
||||
# Build profiling
|
||||
RUN apt-get update && apt-get install -y time && apt-get clean
|
||||
|
||||
#================
|
||||
# C# dependencies
|
||||
|
||||
# Update to a newer version of mono
|
||||
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
|
||||
RUN echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list
|
||||
RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
|
||||
RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
|
||||
RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \
|
||||
mono-devel \
|
||||
ca-certificates-mono \
|
||||
nuget \
|
||||
&& apt-get clean
|
||||
|
||||
#=================
|
||||
# C++ dependencies
|
||||
RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
|
||||
|
||||
#==================
|
||||
# Node dependencies
|
||||
|
||||
# Install nvm
|
||||
RUN touch .profile
|
||||
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
|
||||
RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache"
|
||||
|
||||
#=================
|
||||
# PHP dependencies
|
||||
|
||||
# Install dependencies
|
||||
|
||||
RUN /bin/bash -l -c "echo 'deb http://packages.dotdeb.org wheezy-php55 all' \
|
||||
>> /etc/apt/sources.list.d/dotdeb.list"
|
||||
RUN /bin/bash -l -c "echo 'deb-src http://packages.dotdeb.org wheezy-php55 all' \
|
||||
>> /etc/apt/sources.list.d/dotdeb.list"
|
||||
RUN wget http://www.dotdeb.org/dotdeb.gpg -O- | apt-key add -
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
git php5 php5-dev phpunit unzip
|
||||
|
||||
#==================
|
||||
# Ruby dependencies
|
||||
|
||||
# Install rvm
|
||||
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
|
||||
RUN \curl -sSL https://get.rvm.io | bash -s stable
|
||||
|
||||
# Install Ruby 2.1
|
||||
RUN /bin/bash -l -c "rvm install ruby-2.1"
|
||||
RUN /bin/bash -l -c "rvm use --default ruby-2.1"
|
||||
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
|
||||
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
|
||||
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
|
||||
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
|
||||
|
||||
#====================
|
||||
# Python dependencies
|
||||
|
||||
# Install dependencies
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
python-all-dev \
|
||||
python3-all-dev \
|
||||
python-pip
|
||||
|
||||
# Install Python packages from PyPI
|
||||
RUN pip install pip --upgrade
|
||||
RUN pip install virtualenv
|
||||
RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0a2 tox
|
||||
|
||||
# Prepare ccache
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/g++
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/cc
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/c++
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/clang
|
||||
RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
|
||||
|
||||
#======================
|
||||
# Zookeeper dependencies
|
||||
# TODO(jtattermusch): is zookeeper still needed?
|
||||
RUN apt-get install -y libzookeeper-mt-dev
|
||||
|
||||
RUN mkdir /var/local/jenkins
|
||||
|
||||
# Define the default command.
|
||||
CMD ["bash"]
|
||||
|
|
@ -37,7 +37,7 @@ cd $(dirname $0)
|
|||
CLOUD_PROJECT=grpc-testing
|
||||
ZONE=us-central1-a
|
||||
|
||||
INSTANCE_NAME=grpc-jenkins-worker1
|
||||
INSTANCE_NAME="${1:-grpc-jenkins-worker1}"
|
||||
|
||||
gcloud compute instances create $INSTANCE_NAME \
|
||||
--project="$CLOUD_PROJECT" \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copyright 2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# This script is invoked by Jenkins and runs interop test suite.
|
||||
set -ex
|
||||
|
||||
# Enter the gRPC repo root
|
||||
cd $(dirname $0)/../..
|
||||
|
||||
tools/run_tests/run_interop_tests.py -l all -s all --cloud_to_prod --cloud_to_prod_auth --prod_servers default cloud_gateway gateway_v2 cloud_gateway_v2 gateway_v4 cloud_gateway_v4 --use_docker --http2_interop -t -j 12 $@ || true
|
||||
|
|
@ -69,16 +69,6 @@ def create_jobspec(name, cmdline, environ=None, shell=False,
|
|||
return jobspec
|
||||
|
||||
|
||||
def macos_arch_env(arch):
|
||||
"""Returns environ specifying -arch arguments for make."""
|
||||
if arch == 'x86':
|
||||
arch_arg = '-arch i386'
|
||||
elif arch == 'x64':
|
||||
arch_arg = '-arch x86_64'
|
||||
else:
|
||||
raise Exception('Unsupported arch')
|
||||
return {'CFLAGS': arch_arg, 'LDFLAGS': arch_arg}
|
||||
|
||||
_MACOS_COMPAT_FLAG = '-mmacosx-version-min=10.7'
|
||||
|
||||
_ARCH_FLAG_MAP = {
|
||||
|
|
@ -191,13 +181,17 @@ class CSharpExtArtifact:
|
|||
environ = {'CONFIG': 'opt',
|
||||
'EMBED_OPENSSL': 'true',
|
||||
'EMBED_ZLIB': 'true',
|
||||
'CFLAGS': '-DGPR_BACKWARDS_COMPATIBILITY_MODE'}
|
||||
'CFLAGS': '-DGPR_BACKWARDS_COMPATIBILITY_MODE',
|
||||
'LDFLAGS': ''}
|
||||
if self.platform == 'linux':
|
||||
return create_docker_jobspec(self.name,
|
||||
'tools/dockerfile/grpc_artifact_linux_%s' % self.arch,
|
||||
'tools/run_tests/build_artifact_csharp.sh')
|
||||
'tools/run_tests/build_artifact_csharp.sh',
|
||||
environ=environ)
|
||||
else:
|
||||
environ.update(macos_arch_env(self.arch))
|
||||
archflag = _ARCH_FLAG_MAP[self.arch]
|
||||
environ['CFLAGS'] += ' %s %s' % (archflag, _MACOS_COMPAT_FLAG)
|
||||
environ['LDFLAGS'] += ' %s' % archflag
|
||||
return create_jobspec(self.name,
|
||||
['tools/run_tests/build_artifact_csharp.sh'],
|
||||
environ=environ)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,11 @@ export PATH=$ROOT/bins/$CONFIG:$ROOT/bins/$CONFIG/protobuf:$PATH
|
|||
export CFLAGS="-I$ROOT/include -std=gnu99"
|
||||
export LDFLAGS="-L$ROOT/libs/$CONFIG"
|
||||
export GRPC_PYTHON_BUILD_WITH_CYTHON=1
|
||||
export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
|
||||
|
||||
if [ "$CONFIG" = "gcov" ]
|
||||
then
|
||||
export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
|
||||
fi
|
||||
|
||||
tox --notest
|
||||
|
||||
|
|
|
|||
|
|
@ -589,7 +589,11 @@ prod_servers = {
|
|||
'cloud_gateway': ('216.239.32.255', 'grpc-test.sandbox.googleapis.com',
|
||||
False),
|
||||
'cloud_gateway_v2': ('216.239.32.255', 'grpc-test2.sandbox.googleapis.com',
|
||||
True)
|
||||
True),
|
||||
'gateway_v4': ('grpc-test4.sandbox.googleapis.com',
|
||||
'grpc-test4.sandbox.googleapis.com', True),
|
||||
'cloud_gateway_v4': ('216.239.32.255', 'grpc-test4.sandbox.googleapis.com',
|
||||
True),
|
||||
}
|
||||
|
||||
argp = argparse.ArgumentParser(description='Run interop tests.')
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ export PATH=$ROOT/bins/$CONFIG:$ROOT/bins/$CONFIG/protobuf:$PATH
|
|||
export CFLAGS="-I$ROOT/include -std=c89"
|
||||
export LDFLAGS="-L$ROOT/libs/$CONFIG"
|
||||
export GRPC_PYTHON_BUILD_WITH_CYTHON=1
|
||||
export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
|
||||
|
||||
if [ "$CONFIG" = "gcov" ]
|
||||
then
|
||||
export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
|
||||
tox
|
||||
else
|
||||
$ROOT/.tox/py27/bin/python $ROOT/setup.py test_lite
|
||||
|
|
|
|||
|
|
@ -142,9 +142,8 @@ class CLanguage(object):
|
|||
self._make_options = [_windows_toolset_option(self.args.compiler),
|
||||
_windows_arch_option(self.args.arch)]
|
||||
else:
|
||||
self._make_options = []
|
||||
self._docker_distro = self._get_docker_distro(self.args.use_docker,
|
||||
self.args.compiler)
|
||||
self._docker_distro, self._make_options = self._compiler_options(self.args.use_docker,
|
||||
self.args.compiler)
|
||||
|
||||
def test_specs(self):
|
||||
out = []
|
||||
|
|
@ -229,18 +228,26 @@ class CLanguage(object):
|
|||
def makefile_name(self):
|
||||
return 'Makefile'
|
||||
|
||||
def _get_docker_distro(self, use_docker, compiler):
|
||||
def _clang_make_options(self):
|
||||
return ['CC=clang', 'CXX=clang++', 'LD=clang', 'LDXX=clang++']
|
||||
|
||||
def _compiler_options(self, use_docker, compiler):
|
||||
"""Returns docker distro and make options to use for given compiler."""
|
||||
if _is_use_docker_child():
|
||||
return "already_under_docker"
|
||||
return ("already_under_docker", [])
|
||||
if not use_docker:
|
||||
_check_compiler(compiler, ['default'])
|
||||
|
||||
if compiler == 'gcc4.9' or compiler == 'default':
|
||||
return 'jessie'
|
||||
return ('jessie', [])
|
||||
elif compiler == 'gcc4.4':
|
||||
return 'squeeze'
|
||||
return ('squeeze', [])
|
||||
elif compiler == 'gcc5.3':
|
||||
return 'ubuntu1604'
|
||||
return ('ubuntu1604', [])
|
||||
elif compiler == 'clang3.4':
|
||||
return ('ubuntu1404', self._clang_make_options())
|
||||
elif compiler == 'clang3.6':
|
||||
return ('ubuntu1604', self._clang_make_options())
|
||||
else:
|
||||
raise Exception('Compiler %s not supported.' % compiler)
|
||||
|
||||
|
|
@ -360,7 +367,7 @@ class PythonLanguage(object):
|
|||
['tools/run_tests/run_python.sh'],
|
||||
None,
|
||||
environ=dict(environment.items() +
|
||||
[('GPRC_PYTHON_TESTRUNNER_FILTER', suite_name)]),
|
||||
[('GRPC_PYTHON_TESTRUNNER_FILTER', suite_name)]),
|
||||
shortname='py.test.%s' % suite_name,
|
||||
timeout_seconds=5*60)
|
||||
for suite_name in tests_json]
|
||||
|
|
@ -774,6 +781,7 @@ argp.add_argument('--arch',
|
|||
argp.add_argument('--compiler',
|
||||
choices=['default',
|
||||
'gcc4.4', 'gcc4.9', 'gcc5.3',
|
||||
'clang3.4', 'clang3.6',
|
||||
'vs2010', 'vs2013', 'vs2015'],
|
||||
default='default',
|
||||
help='Selects compiler to use. Allowed values depend on the platform and language.')
|
||||
|
|
@ -861,10 +869,17 @@ if args.use_docker:
|
|||
|
||||
dockerfile_dirs = set([l.dockerfile_dir() for l in languages])
|
||||
if len(dockerfile_dirs) > 1:
|
||||
print 'Languages to be tested require running under different docker images.'
|
||||
sys.exit(1)
|
||||
dockerfile_dir = next(iter(dockerfile_dirs))
|
||||
|
||||
if 'gcov' in args.config:
|
||||
dockerfile_dir = 'tools/dockerfile/test/multilang_jessie_x64'
|
||||
print ('Using multilang_jessie_x64 docker image for code coverage for '
|
||||
'all languages.')
|
||||
else:
|
||||
print ('Languages to be tested require running under different docker '
|
||||
'images.')
|
||||
sys.exit(1)
|
||||
else:
|
||||
dockerfile_dir = next(iter(dockerfile_dirs))
|
||||
|
||||
child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
|
||||
run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
- script: tools/run_tests/sanity/check_cache_mk.sh
|
||||
- script: tools/run_tests/sanity/check_sources_and_headers.py
|
||||
- script: tools/run_tests/sanity/check_submodules.sh
|
||||
- script: tools/run_tests/sanity/check_version.py
|
||||
- script: tools/buildgen/generate_projects.sh -j 3
|
||||
cpu_cost: 3
|
||||
- script: tools/distrib/check_copyright.py
|
||||
|
|
|
|||
|
|
@ -189,6 +189,38 @@
|
|||
"third_party": false,
|
||||
"type": "target"
|
||||
},
|
||||
{
|
||||
"deps": [
|
||||
"gpr",
|
||||
"gpr_test_util",
|
||||
"grpc",
|
||||
"grpc_test_util"
|
||||
],
|
||||
"headers": [],
|
||||
"language": "c",
|
||||
"name": "concurrent_connectivity_test",
|
||||
"src": [
|
||||
"test/core/surface/concurrent_connectivity_test.c"
|
||||
],
|
||||
"third_party": false,
|
||||
"type": "target"
|
||||
},
|
||||
{
|
||||
"deps": [
|
||||
"gpr",
|
||||
"gpr_test_util",
|
||||
"grpc",
|
||||
"grpc_test_util"
|
||||
],
|
||||
"headers": [],
|
||||
"language": "c",
|
||||
"name": "dns_resolver_connectivity_test",
|
||||
"src": [
|
||||
"test/core/client_config/resolvers/dns_resolver_connectivity_test.c"
|
||||
],
|
||||
"third_party": false,
|
||||
"type": "target"
|
||||
},
|
||||
{
|
||||
"deps": [
|
||||
"gpr",
|
||||
|
|
|
|||
|
|
@ -253,6 +253,48 @@
|
|||
"windows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"ci_platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
],
|
||||
"cpu_cost": 1.0,
|
||||
"exclude_configs": [],
|
||||
"flaky": false,
|
||||
"gtest": false,
|
||||
"language": "c",
|
||||
"name": "concurrent_connectivity_test",
|
||||
"platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"ci_platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
],
|
||||
"cpu_cost": 0.1,
|
||||
"exclude_configs": [],
|
||||
"flaky": false,
|
||||
"gtest": false,
|
||||
"language": "c",
|
||||
"name": "dns_resolver_connectivity_test",
|
||||
"platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"ci_platforms": [
|
||||
|
|
|
|||
|
|
@ -258,6 +258,28 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "compression_test", "vcxproj
|
|||
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "concurrent_connectivity_test", "vcxproj\test\concurrent_connectivity_test\concurrent_connectivity_test.vcxproj", "{391B366C-D916-45AA-3FE5-67363A46193B}"
|
||||
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}") = "dns_resolver_connectivity_test", "vcxproj\test\dns_resolver_connectivity_test\dns_resolver_connectivity_test.vcxproj", "{F7B6FE68-E847-D7CA-4062-E737E542BCC3}"
|
||||
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}") = "dns_resolver_test", "vcxproj\test\dns_resolver_test\dns_resolver_test.vcxproj", "{D06E10DC-272A-5203-7066-2698A247DF26}"
|
||||
ProjectSection(myProperties) = preProject
|
||||
lib = "False"
|
||||
|
|
@ -1759,6 +1781,38 @@ Global
|
|||
{5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Release-DLL|Win32.Build.0 = Release|Win32
|
||||
{5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Release-DLL|x64.ActiveCfg = Release|x64
|
||||
{5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Release-DLL|x64.Build.0 = Release|x64
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Release|x64.ActiveCfg = Release|x64
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Debug|x64.Build.0 = Debug|x64
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Release|Win32.Build.0 = Release|Win32
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Release|x64.Build.0 = Release|x64
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Debug-DLL|Win32.Build.0 = Debug|Win32
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Debug-DLL|x64.ActiveCfg = Debug|x64
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Debug-DLL|x64.Build.0 = Debug|x64
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Release-DLL|Win32.ActiveCfg = Release|Win32
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Release-DLL|Win32.Build.0 = Release|Win32
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Release-DLL|x64.ActiveCfg = Release|x64
|
||||
{391B366C-D916-45AA-3FE5-67363A46193B}.Release-DLL|x64.Build.0 = Release|x64
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Release|x64.ActiveCfg = Release|x64
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Debug|x64.Build.0 = Debug|x64
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Release|Win32.Build.0 = Release|Win32
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Release|x64.Build.0 = Release|x64
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Debug-DLL|Win32.Build.0 = Debug|Win32
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Debug-DLL|x64.ActiveCfg = Debug|x64
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Debug-DLL|x64.Build.0 = Debug|x64
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Release-DLL|Win32.ActiveCfg = Release|Win32
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Release-DLL|Win32.Build.0 = Release|Win32
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Release-DLL|x64.ActiveCfg = Release|x64
|
||||
{F7B6FE68-E847-D7CA-4062-E737E542BCC3}.Release-DLL|x64.Build.0 = Release|x64
|
||||
{D06E10DC-272A-5203-7066-2698A247DF26}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D06E10DC-272A-5203-7066-2698A247DF26}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D06E10DC-272A-5203-7066-2698A247DF26}.Release|Win32.ActiveCfg = Release|Win32
|
||||
|
|
|
|||
|
|
@ -0,0 +1,199 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\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>{391B366C-D916-45AA-3FE5-67363A46193B}</ProjectGuid>
|
||||
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
|
||||
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
|
||||
</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="$(SolutionDir)\..\vsprojects\global.props" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<TargetName>concurrent_connectivity_test</TargetName>
|
||||
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
|
||||
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
|
||||
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
|
||||
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<TargetName>concurrent_connectivity_test</TargetName>
|
||||
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
|
||||
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
|
||||
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
|
||||
<Configuration-grpc_dependencies_openssl>Release</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>
|
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
|
||||
</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>
|
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
|
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
|
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
|
||||
</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>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
|
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
|
||||
</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="$(SolutionDir)\..\test\core\surface\concurrent_connectivity_test.c">
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
|
||||
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
|
||||
<Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
|
||||
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)\..\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="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\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('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
|
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
|
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
|
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
|
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
|
|
@ -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="$(SolutionDir)\..\test\core\surface\concurrent_connectivity_test.c">
|
||||
<Filter>test\core\surface</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Filter Include="test">
|
||||
<UniqueIdentifier>{1320b717-a107-004b-c517-074e6a7baf97}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="test\core">
|
||||
<UniqueIdentifier>{f205219c-cee2-c0e8-a922-5486f2d31026}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="test\core\surface">
|
||||
<UniqueIdentifier>{6804b6ae-88f4-acf9-b3fc-6b12f8e28d4d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\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>{F7B6FE68-E847-D7CA-4062-E737E542BCC3}</ProjectGuid>
|
||||
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
|
||||
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
|
||||
</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="$(SolutionDir)\..\vsprojects\global.props" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<TargetName>dns_resolver_connectivity_test</TargetName>
|
||||
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
|
||||
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
|
||||
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
|
||||
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<TargetName>dns_resolver_connectivity_test</TargetName>
|
||||
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
|
||||
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
|
||||
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
|
||||
<Configuration-grpc_dependencies_openssl>Release</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>
|
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
|
||||
</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>
|
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
|
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
|
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
|
||||
</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>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
|
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
|
||||
</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="$(SolutionDir)\..\test\core\client_config\resolvers\dns_resolver_connectivity_test.c">
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
|
||||
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
|
||||
<Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
|
||||
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)\..\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="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
|
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\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('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
|
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
|
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
|
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
|
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
|
|
@ -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="$(SolutionDir)\..\test\core\client_config\resolvers\dns_resolver_connectivity_test.c">
|
||||
<Filter>test\core\client_config\resolvers</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Filter Include="test">
|
||||
<UniqueIdentifier>{7743e287-3311-1206-2766-32381628ff07}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="test\core">
|
||||
<UniqueIdentifier>{cc06b800-cd26-f7a8-7ecf-ec789e78881b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="test\core\client_config">
|
||||
<UniqueIdentifier>{4fbd5c0a-d1e3-6658-5788-2fc6f2cc9071}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="test\core\client_config\resolvers">
|
||||
<UniqueIdentifier>{eab637a2-7ac1-f6be-4fc2-c8989c66070b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Loading…
Reference in New Issue