Merge pull request #10436 from dgquintas/fake_resolver_args

Improvements to Fake Resolver
pull/10674/head
David G. Quintas 8 years ago committed by GitHub
commit 0ece13a229
  1. 32
      CMakeLists.txt
  2. 36
      Makefile
  3. 10
      build.yaml
  4. 33
      src/core/ext/filters/client_channel/lb_policy_factory.c
  5. 22
      src/core/ext/filters/client_channel/lb_policy_factory.h
  6. 44
      src/core/ext/filters/client_channel/parse_address.c
  7. 19
      src/core/ext/filters/client_channel/parse_address.h
  8. 6
      src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c
  9. 8
      src/core/ext/filters/client_channel/subchannel.c
  10. 4
      src/core/ext/filters/client_channel/uri_parser.c
  11. 2
      src/core/ext/filters/client_channel/uri_parser.h
  12. 11
      src/core/lib/channel/channel_args.c
  13. 3
      src/core/lib/channel/channel_args.h
  14. 2
      src/core/lib/iomgr/sockaddr_utils.h
  15. 23
      src/core/lib/security/credentials/fake/fake_credentials.c
  16. 21
      src/core/lib/security/credentials/fake/fake_credentials.h
  17. 8
      src/core/lib/security/transport/security_connector.c
  18. 26
      test/core/client_channel/parse_address_test.c
  19. 40
      test/core/client_channel/resolvers/BUILD
  20. 187
      test/core/client_channel/resolvers/fake_resolver_test.c
  21. 79
      test/core/end2end/BUILD
  22. 211
      test/core/end2end/fake_resolver.c
  23. 34
      test/core/end2end/fake_resolver.h
  24. 45
      test/cpp/grpclb/grpclb_test.cc
  25. 17
      tools/run_tests/generated/sources_and_headers.json
  26. 22
      tools/run_tests/generated/tests.json
  27. 27
      vsprojects/buildtests_c.sln
  28. 199
      vsprojects/vcxproj/test/fake_resolver_test/fake_resolver_test.vcxproj
  29. 24
      vsprojects/vcxproj/test/fake_resolver_test/fake_resolver_test.vcxproj.filters

@ -391,6 +391,7 @@ add_dependencies(buildtests_c error_test)
if(_gRPC_PLATFORM_LINUX) if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c ev_epoll_linux_test) add_dependencies(buildtests_c ev_epoll_linux_test)
endif() endif()
add_dependencies(buildtests_c fake_resolver_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c fd_conservation_posix_test) add_dependencies(buildtests_c fd_conservation_posix_test)
endif() endif()
@ -5444,6 +5445,37 @@ target_link_libraries(ev_epoll_linux_test
) )
endif() endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(fake_resolver_test
test/core/client_channel/resolvers/fake_resolver_test.c
)
target_include_directories(fake_resolver_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(fake_resolver_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)

@ -981,6 +981,7 @@ dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test
endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
error_test: $(BINDIR)/$(CONFIG)/error_test error_test: $(BINDIR)/$(CONFIG)/error_test
ev_epoll_linux_test: $(BINDIR)/$(CONFIG)/ev_epoll_linux_test ev_epoll_linux_test: $(BINDIR)/$(CONFIG)/ev_epoll_linux_test
fake_resolver_test: $(BINDIR)/$(CONFIG)/fake_resolver_test
fd_conservation_posix_test: $(BINDIR)/$(CONFIG)/fd_conservation_posix_test fd_conservation_posix_test: $(BINDIR)/$(CONFIG)/fd_conservation_posix_test
fd_posix_test: $(BINDIR)/$(CONFIG)/fd_posix_test fd_posix_test: $(BINDIR)/$(CONFIG)/fd_posix_test
fling_client: $(BINDIR)/$(CONFIG)/fling_client fling_client: $(BINDIR)/$(CONFIG)/fling_client
@ -1366,6 +1367,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/endpoint_pair_test \ $(BINDIR)/$(CONFIG)/endpoint_pair_test \
$(BINDIR)/$(CONFIG)/error_test \ $(BINDIR)/$(CONFIG)/error_test \
$(BINDIR)/$(CONFIG)/ev_epoll_linux_test \ $(BINDIR)/$(CONFIG)/ev_epoll_linux_test \
$(BINDIR)/$(CONFIG)/fake_resolver_test \
$(BINDIR)/$(CONFIG)/fd_conservation_posix_test \ $(BINDIR)/$(CONFIG)/fd_conservation_posix_test \
$(BINDIR)/$(CONFIG)/fd_posix_test \ $(BINDIR)/$(CONFIG)/fd_posix_test \
$(BINDIR)/$(CONFIG)/fling_client \ $(BINDIR)/$(CONFIG)/fling_client \
@ -1777,6 +1779,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/error_test || ( echo test error_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/error_test || ( echo test error_test failed ; exit 1 )
$(E) "[RUN] Testing ev_epoll_linux_test" $(E) "[RUN] Testing ev_epoll_linux_test"
$(Q) $(BINDIR)/$(CONFIG)/ev_epoll_linux_test || ( echo test ev_epoll_linux_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/ev_epoll_linux_test || ( echo test ev_epoll_linux_test failed ; exit 1 )
$(E) "[RUN] Testing fake_resolver_test"
$(Q) $(BINDIR)/$(CONFIG)/fake_resolver_test || ( echo test fake_resolver_test failed ; exit 1 )
$(E) "[RUN] Testing fd_conservation_posix_test" $(E) "[RUN] Testing fd_conservation_posix_test"
$(Q) $(BINDIR)/$(CONFIG)/fd_conservation_posix_test || ( echo test fd_conservation_posix_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/fd_conservation_posix_test || ( echo test fd_conservation_posix_test failed ; exit 1 )
$(E) "[RUN] Testing fd_posix_test" $(E) "[RUN] Testing fd_posix_test"
@ -9401,6 +9405,38 @@ endif
endif endif
FAKE_RESOLVER_TEST_SRC = \
test/core/client_channel/resolvers/fake_resolver_test.c \
FAKE_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FAKE_RESOLVER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/fake_resolver_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/fake_resolver_test: $(FAKE_RESOLVER_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) $(FAKE_RESOLVER_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)/fake_resolver_test
endif
$(OBJDIR)/$(CONFIG)/test/core/client_channel/resolvers/fake_resolver_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_fake_resolver_test: $(FAKE_RESOLVER_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(FAKE_RESOLVER_TEST_OBJS:.o=.dep)
endif
endif
FD_CONSERVATION_POSIX_TEST_SRC = \ FD_CONSERVATION_POSIX_TEST_SRC = \
test/core/iomgr/fd_conservation_posix_test.c \ test/core/iomgr/fd_conservation_posix_test.c \

@ -1820,6 +1820,16 @@ targets:
- uv - uv
platforms: platforms:
- linux - linux
- name: fake_resolver_test
build: test
language: c
src:
- test/core/client_channel/resolvers/fake_resolver_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: fd_conservation_posix_test - name: fd_conservation_posix_test
build: test build: test
language: c language: c

@ -36,16 +36,18 @@
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/ext/filters/client_channel/parse_address.h"
grpc_lb_addresses* grpc_lb_addresses_create( grpc_lb_addresses* grpc_lb_addresses_create(
size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) { size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) {
grpc_lb_addresses* addresses = gpr_malloc(sizeof(grpc_lb_addresses)); grpc_lb_addresses* addresses = gpr_zalloc(sizeof(grpc_lb_addresses));
addresses->num_addresses = num_addresses; addresses->num_addresses = num_addresses;
addresses->user_data_vtable = user_data_vtable; addresses->user_data_vtable = user_data_vtable;
const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses; const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses;
addresses->addresses = gpr_malloc(addresses_size); addresses->addresses = gpr_zalloc(addresses_size);
memset(addresses->addresses, 0, addresses_size);
return addresses; return addresses;
} }
@ -69,7 +71,7 @@ grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses) {
void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index, void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
void* address, size_t address_len, void* address, size_t address_len,
bool is_balancer, char* balancer_name, bool is_balancer, const char* balancer_name,
void* user_data) { void* user_data) {
GPR_ASSERT(index < addresses->num_addresses); GPR_ASSERT(index < addresses->num_addresses);
if (user_data != NULL) GPR_ASSERT(addresses->user_data_vtable != NULL); if (user_data != NULL) GPR_ASSERT(addresses->user_data_vtable != NULL);
@ -77,10 +79,22 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
memcpy(target->address.addr, address, address_len); memcpy(target->address.addr, address, address_len);
target->address.len = address_len; target->address.len = address_len;
target->is_balancer = is_balancer; target->is_balancer = is_balancer;
target->balancer_name = balancer_name; target->balancer_name = gpr_strdup(balancer_name);
target->user_data = user_data; target->user_data = user_data;
} }
bool grpc_lb_addresses_set_address_from_uri(grpc_lb_addresses* addresses,
size_t index, const grpc_uri* uri,
bool is_balancer,
const char* balancer_name,
void* user_data) {
grpc_resolved_address address;
if (!grpc_parse_uri(uri, &address)) return false;
grpc_lb_addresses_set_address(addresses, index, address.addr, address.len,
is_balancer, balancer_name, user_data);
return true;
}
int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1, int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1,
const grpc_lb_addresses* addresses2) { const grpc_lb_addresses* addresses2) {
if (addresses1->num_addresses > addresses2->num_addresses) return 1; if (addresses1->num_addresses > addresses2->num_addresses) return 1;
@ -147,6 +161,15 @@ grpc_arg grpc_lb_addresses_create_channel_arg(
return arg; return arg;
} }
grpc_lb_addresses* grpc_lb_addresses_find_channel_arg(
const grpc_channel_args* channel_args) {
const grpc_arg* lb_addresses_arg =
grpc_channel_args_find(channel_args, GRPC_ARG_LB_ADDRESSES);
if (lb_addresses_arg == NULL || lb_addresses_arg->type != GRPC_ARG_POINTER)
return NULL;
return lb_addresses_arg->value.pointer.p;
}
void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) { void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) {
factory->vtable->ref(factory); factory->vtable->ref(factory);
} }

@ -34,12 +34,13 @@
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H
#include "src/core/ext/filters/client_channel/client_channel_factory.h"
#include "src/core/ext/filters/client_channel/lb_policy.h"
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/ext/filters/client_channel/client_channel_factory.h"
#include "src/core/ext/filters/client_channel/lb_policy.h"
#include "src/core/ext/filters/client_channel/uri_parser.h"
// Channel arg key for grpc_lb_addresses. // Channel arg key for grpc_lb_addresses.
#define GRPC_ARG_LB_ADDRESSES "grpc.lb_addresses" #define GRPC_ARG_LB_ADDRESSES "grpc.lb_addresses"
@ -88,9 +89,18 @@ grpc_lb_addresses *grpc_lb_addresses_copy(const grpc_lb_addresses *addresses);
* Takes ownership of \a balancer_name. */ * Takes ownership of \a balancer_name. */
void grpc_lb_addresses_set_address(grpc_lb_addresses *addresses, size_t index, void grpc_lb_addresses_set_address(grpc_lb_addresses *addresses, size_t index,
void *address, size_t address_len, void *address, size_t address_len,
bool is_balancer, char *balancer_name, bool is_balancer, const char *balancer_name,
void *user_data); void *user_data);
/** Sets the value of the address at index \a index of \a addresses from \a uri.
* Returns true upon success, false otherwise. Takes ownership of \a
* balancer_name. */
bool grpc_lb_addresses_set_address_from_uri(grpc_lb_addresses *addresses,
size_t index, const grpc_uri *uri,
bool is_balancer,
const char *balancer_name,
void *user_data);
/** Compares \a addresses1 and \a addresses2. */ /** Compares \a addresses1 and \a addresses2. */
int grpc_lb_addresses_cmp(const grpc_lb_addresses *addresses1, int grpc_lb_addresses_cmp(const grpc_lb_addresses *addresses1,
const grpc_lb_addresses *addresses2); const grpc_lb_addresses *addresses2);
@ -103,6 +113,10 @@ void grpc_lb_addresses_destroy(grpc_exec_ctx *exec_ctx,
grpc_arg grpc_lb_addresses_create_channel_arg( grpc_arg grpc_lb_addresses_create_channel_arg(
const grpc_lb_addresses *addresses); const grpc_lb_addresses *addresses);
/** Returns the \a grpc_lb_addresses instance in \a channel_args or NULL */
grpc_lb_addresses *grpc_lb_addresses_find_channel_arg(
const grpc_channel_args *channel_args);
/** Arguments passed to LB policies. */ /** Arguments passed to LB policies. */
typedef struct grpc_lb_policy_args { typedef struct grpc_lb_policy_args {
grpc_client_channel_factory *client_channel_factory; grpc_client_channel_factory *client_channel_factory;

@ -48,7 +48,12 @@
#ifdef GRPC_HAVE_UNIX_SOCKET #ifdef GRPC_HAVE_UNIX_SOCKET
int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr) { bool grpc_parse_unix(const grpc_uri *uri,
grpc_resolved_address *resolved_addr) {
if (strcmp("unix", uri->scheme) != 0) {
gpr_log(GPR_ERROR, "Expected 'unix' scheme, got '%s'", uri->scheme);
return false;
}
struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr; struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr;
const size_t maxlen = sizeof(un->sun_path); const size_t maxlen = sizeof(un->sun_path);
const size_t path_len = strnlen(uri->path, maxlen); const size_t path_len = strnlen(uri->path, maxlen);
@ -61,21 +66,29 @@ int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
#else /* GRPC_HAVE_UNIX_SOCKET */ #else /* GRPC_HAVE_UNIX_SOCKET */
int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr) { abort(); } bool grpc_parse_unix(const grpc_uri *uri,
grpc_resolved_address *resolved_addr) {
abort();
}
#endif /* GRPC_HAVE_UNIX_SOCKET */ #endif /* GRPC_HAVE_UNIX_SOCKET */
int parse_ipv4(grpc_uri *uri, grpc_resolved_address *resolved_addr) { bool grpc_parse_ipv4(const grpc_uri *uri,
grpc_resolved_address *resolved_addr) {
if (strcmp("ipv4", uri->scheme) != 0) {
gpr_log(GPR_ERROR, "Expected 'ipv4' scheme, got '%s'", uri->scheme);
return false;
}
const char *host_port = uri->path; const char *host_port = uri->path;
char *host; char *host;
char *port; char *port;
int port_num; int port_num;
int result = 0; bool result = false;
struct sockaddr_in *in = (struct sockaddr_in *)resolved_addr->addr; struct sockaddr_in *in = (struct sockaddr_in *)resolved_addr->addr;
if (*host_port == '/') ++host_port; if (*host_port == '/') ++host_port;
if (!gpr_split_host_port(host_port, &host, &port)) { if (!gpr_split_host_port(host_port, &host, &port)) {
return 0; return false;
} }
memset(resolved_addr, 0, sizeof(grpc_resolved_address)); memset(resolved_addr, 0, sizeof(grpc_resolved_address));
@ -98,14 +111,19 @@ int parse_ipv4(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
goto done; goto done;
} }
result = 1; result = true;
done: done:
gpr_free(host); gpr_free(host);
gpr_free(port); gpr_free(port);
return result; return result;
} }
int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr) { bool grpc_parse_ipv6(const grpc_uri *uri,
grpc_resolved_address *resolved_addr) {
if (strcmp("ipv6", uri->scheme) != 0) {
gpr_log(GPR_ERROR, "Expected 'ipv6' scheme, got '%s'", uri->scheme);
return false;
}
const char *host_port = uri->path; const char *host_port = uri->path;
char *host; char *host;
char *port; char *port;
@ -168,3 +186,15 @@ done:
gpr_free(port); gpr_free(port);
return result; return result;
} }
bool grpc_parse_uri(const grpc_uri *uri, grpc_resolved_address *resolved_addr) {
if (strcmp("unix", uri->scheme) == 0) {
return grpc_parse_unix(uri, resolved_addr);
} else if (strcmp("ipv4", uri->scheme) == 0) {
return grpc_parse_ipv4(uri, resolved_addr);
} else if (strcmp("ipv6", uri->scheme) == 0) {
return grpc_parse_ipv6(uri, resolved_addr);
}
gpr_log(GPR_ERROR, "Can't parse scheme '%s'", uri->scheme);
return false;
}

@ -39,16 +39,19 @@
#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/ext/filters/client_channel/uri_parser.h"
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
/** Populate \a addr and \a len from \a uri, whose path is expected to contain a /** Populate \a resolved_addr from \a uri, whose path is expected to contain a
* unix socket path. Returns true upon success. */ * unix socket path. Returns true upon success. */
int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr); bool grpc_parse_unix(const grpc_uri *uri, grpc_resolved_address *resolved_addr);
/** Populate /a addr and \a len from \a uri, whose path is expected to contain a /** Populate \a resolved_addr from \a uri, whose path is expected to contain an
* host:port pair. Returns true upon success. */ * IPv4 host:port pair. Returns true upon success. */
int parse_ipv4(grpc_uri *uri, grpc_resolved_address *resolved_addr); bool grpc_parse_ipv4(const grpc_uri *uri, grpc_resolved_address *resolved_addr);
/** Populate /a addr and \a len from \a uri, whose path is expected to contain a /** Populate \a resolved_addr from \a uri, whose path is expected to contain an
* host:port pair. Returns true upon success. */ * IPv6 host:port pair. Returns true upon success. */
int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr); bool grpc_parse_ipv6(const grpc_uri *uri, grpc_resolved_address *resolved_addr);
/** Populate \a resolved_addr from \a uri. Returns true upon success. */
bool grpc_parse_uri(const grpc_uri *uri, grpc_resolved_address *resolved_addr);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */

@ -157,8 +157,8 @@ static void do_nothing(void *ignored) {}
static grpc_resolver *sockaddr_create(grpc_exec_ctx *exec_ctx, static grpc_resolver *sockaddr_create(grpc_exec_ctx *exec_ctx,
grpc_resolver_args *args, grpc_resolver_args *args,
int parse(grpc_uri *uri, bool parse(const grpc_uri *uri,
grpc_resolved_address *dst)) { grpc_resolved_address *dst)) {
if (0 != strcmp(args->uri->authority, "")) { if (0 != strcmp(args->uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme", gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme",
args->uri->scheme); args->uri->scheme);
@ -209,7 +209,7 @@ static void sockaddr_factory_unref(grpc_resolver_factory *factory) {}
static grpc_resolver *name##_factory_create_resolver( \ static grpc_resolver *name##_factory_create_resolver( \
grpc_exec_ctx *exec_ctx, grpc_resolver_factory *factory, \ grpc_exec_ctx *exec_ctx, grpc_resolver_factory *factory, \
grpc_resolver_args *args) { \ grpc_resolver_args *args) { \
return sockaddr_create(exec_ctx, args, parse_##name); \ return sockaddr_create(exec_ctx, args, grpc_parse_##name); \
} \ } \
static const grpc_resolver_factory_vtable name##_factory_vtable = { \ static const grpc_resolver_factory_vtable name##_factory_vtable = { \
sockaddr_factory_ref, sockaddr_factory_unref, \ sockaddr_factory_ref, sockaddr_factory_unref, \

@ -797,13 +797,7 @@ static void grpc_uri_to_sockaddr(grpc_exec_ctx *exec_ctx, const char *uri_str,
grpc_resolved_address *addr) { grpc_resolved_address *addr) {
grpc_uri *uri = grpc_uri_parse(exec_ctx, uri_str, 0 /* suppress_errors */); grpc_uri *uri = grpc_uri_parse(exec_ctx, uri_str, 0 /* suppress_errors */);
GPR_ASSERT(uri != NULL); GPR_ASSERT(uri != NULL);
if (strcmp(uri->scheme, "ipv4") == 0) { if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr));
GPR_ASSERT(parse_ipv4(uri, addr));
} else if (strcmp(uri->scheme, "ipv6") == 0) {
GPR_ASSERT(parse_ipv6(uri, addr));
} else {
GPR_ASSERT(parse_unix(uri, addr));
}
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
} }

@ -50,7 +50,7 @@
#define NOT_SET (~(size_t)0) #define NOT_SET (~(size_t)0)
static grpc_uri *bad_uri(const char *uri_text, size_t pos, const char *section, static grpc_uri *bad_uri(const char *uri_text, size_t pos, const char *section,
int suppress_errors) { bool suppress_errors) {
char *line_prefix; char *line_prefix;
size_t pfx_len; size_t pfx_len;
@ -197,7 +197,7 @@ static void parse_query_parts(grpc_uri *uri) {
} }
grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text, grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text,
int suppress_errors) { bool suppress_errors) {
grpc_uri *uri; grpc_uri *uri;
size_t scheme_begin = 0; size_t scheme_begin = 0;
size_t scheme_end = NOT_SET; size_t scheme_end = NOT_SET;

@ -53,7 +53,7 @@ typedef struct {
/** parse a uri, return NULL on failure */ /** parse a uri, return NULL on failure */
grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text, grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text,
int suppress_errors); bool suppress_errors);
/** return the part of a query string after the '=' in "?key=xxx&...", or NULL /** return the part of a query string after the '=' in "?key=xxx&...", or NULL
* if key is not present */ * if key is not present */

@ -31,17 +31,18 @@
* *
*/ */
#include "src/core/lib/channel/channel_args.h" #include <limits.h>
#include <grpc/grpc.h> #include <string.h>
#include "src/core/lib/support/string.h"
#include <grpc/compression.h> #include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include <string.h> #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/support/string.h"
static grpc_arg copy_arg(const grpc_arg *src) { static grpc_arg copy_arg(const grpc_arg *src) {
grpc_arg dst; grpc_arg dst;
@ -330,7 +331,7 @@ const grpc_arg *grpc_channel_args_find(const grpc_channel_args *args,
} }
int grpc_channel_arg_get_integer(const grpc_arg *arg, int grpc_channel_arg_get_integer(const grpc_arg *arg,
grpc_integer_options options) { const grpc_integer_options options) {
if (arg == NULL) return options.default_value; if (arg == NULL) return options.default_value;
if (arg->type != GRPC_ARG_INTEGER) { if (arg->type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s ignored: it must be an integer", arg->key); gpr_log(GPR_ERROR, "%s ignored: it must be an integer", arg->key);

@ -120,9 +120,10 @@ typedef struct grpc_integer_options {
int min_value; int min_value;
int max_value; int max_value;
} grpc_integer_options; } grpc_integer_options;
/** Returns the value of \a arg, subject to the contraints in \a options. */ /** Returns the value of \a arg, subject to the contraints in \a options. */
int grpc_channel_arg_get_integer(const grpc_arg *arg, int grpc_channel_arg_get_integer(const grpc_arg *arg,
grpc_integer_options options); const grpc_integer_options options);
bool grpc_channel_arg_get_bool(const grpc_arg *arg, bool default_value); bool grpc_channel_arg_get_bool(const grpc_arg *arg, bool default_value);

@ -50,7 +50,7 @@ int grpc_sockaddr_to_v4mapped(const grpc_resolved_address *addr,
grpc_resolved_address *addr6_out); grpc_resolved_address *addr6_out);
/* If addr is ::, 0.0.0.0, or ::ffff:0.0.0.0, writes the port number to /* If addr is ::, 0.0.0.0, or ::ffff:0.0.0.0, writes the port number to
*port_out (if not NULL) and returns true, otherwise returns false. */ *port_out (if not NULL) and returns true, otherwise returns false. */
int grpc_sockaddr_is_wildcard(const grpc_resolved_address *addr, int *port_out); int grpc_sockaddr_is_wildcard(const grpc_resolved_address *addr, int *port_out);
/* Writes 0.0.0.0:port and [::]:port to separate sockaddrs. */ /* Writes 0.0.0.0:port and [::]:port to separate sockaddrs. */

@ -39,11 +39,15 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
/* -- Fake transport security credentials. -- */ /* -- Fake transport security credentials. -- */
#define GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS \
"grpc.fake_security.expected_targets"
static grpc_security_status fake_transport_security_create_security_connector( static grpc_security_status fake_transport_security_create_security_connector(
grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c, grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c,
grpc_call_credentials *call_creds, const char *target, grpc_call_credentials *call_creds, const char *target,
@ -88,6 +92,25 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
return c; return c;
} }
grpc_arg grpc_fake_transport_expected_targets_arg(char *expected_targets) {
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS;
arg.value.string = expected_targets;
return arg;
}
const char *grpc_fake_transport_get_expected_targets(
const grpc_channel_args *args) {
const grpc_arg *expected_target_arg =
grpc_channel_args_find(args, GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS);
if (expected_target_arg != NULL &&
expected_target_arg->type == GRPC_ARG_STRING) {
return expected_target_arg->value.string;
}
return NULL;
}
/* -- Metadata-only test credentials. -- */ /* -- Metadata-only test credentials. -- */
static void md_only_test_destruct(grpc_exec_ctx *exec_ctx, static void md_only_test_destruct(grpc_exec_ctx *exec_ctx,

@ -38,10 +38,17 @@
/* -- Fake transport security credentials. -- */ /* -- Fake transport security credentials. -- */
/* Creates a fake transport security credentials object for testing. */
grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void);
/* Creates a fake server transport security credentials object for testing. */
grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
void);
/* Used to verify the target names given to the fake transport security /* Used to verify the target names given to the fake transport security
* connector. * connector.
* *
* Its syntax by example: * The syntax of \a expected_targets by example:
* For LB channels: * For LB channels:
* "backend_target_1,backend_target_2,...;lb_target_1,lb_target_2,..." * "backend_target_1,backend_target_2,...;lb_target_1,lb_target_2,..."
* For regular channels: * For regular channels:
@ -50,15 +57,11 @@
* That is to say, LB channels have a heading list of LB targets separated from * That is to say, LB channels have a heading list of LB targets separated from
* the list of backend targets by a semicolon. For non-LB channels, only the * the list of backend targets by a semicolon. For non-LB channels, only the
* latter is present. */ * latter is present. */
#define GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS \ grpc_arg grpc_fake_transport_expected_targets_arg(char *expected_targets);
"grpc.test_only.fake_security.expected_target"
/* Creates a fake transport security credentials object for testing. */ /* Return the value associated with the expected targets channel arg or NULL */
grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void); const char *grpc_fake_transport_get_expected_targets(
const grpc_channel_args *args);
/* Creates a fake server transport security credentials object for testing. */
grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
void);
/* -- Metadata-only Test credentials. -- */ /* -- Metadata-only Test credentials. -- */

@ -423,12 +423,8 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
c->base.check_call_host = fake_channel_check_call_host; c->base.check_call_host = fake_channel_check_call_host;
c->base.add_handshakers = fake_channel_add_handshakers; c->base.add_handshakers = fake_channel_add_handshakers;
c->target = gpr_strdup(target); c->target = gpr_strdup(target);
const grpc_arg *expected_target_arg = const char *expected_targets = grpc_fake_transport_get_expected_targets(args);
grpc_channel_args_find(args, GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS); c->expected_targets = gpr_strdup(expected_targets);
if (expected_target_arg != NULL) {
GPR_ASSERT(expected_target_arg->type == GRPC_ARG_STRING);
c->expected_targets = gpr_strdup(expected_target_arg->value.string);
}
c->is_lb_channel = (grpc_lb_targets_info_find_in_args(args) != NULL); c->is_lb_channel = (grpc_lb_targets_info_find_in_args(args) != NULL);
return &c->base; return &c->base;
} }

@ -47,12 +47,12 @@
#ifdef GRPC_HAVE_UNIX_SOCKET #ifdef GRPC_HAVE_UNIX_SOCKET
static void test_parse_unix(const char *uri_text, const char *pathname) { static void test_grpc_parse_unix(const char *uri_text, const char *pathname) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
grpc_resolved_address addr; grpc_resolved_address addr;
GPR_ASSERT(1 == parse_unix(uri, &addr)); GPR_ASSERT(1 == grpc_parse_unix(uri, &addr));
struct sockaddr_un *addr_un = (struct sockaddr_un *)addr.addr; struct sockaddr_un *addr_un = (struct sockaddr_un *)addr.addr;
GPR_ASSERT(AF_UNIX == addr_un->sun_family); GPR_ASSERT(AF_UNIX == addr_un->sun_family);
GPR_ASSERT(0 == strcmp(addr_un->sun_path, pathname)); GPR_ASSERT(0 == strcmp(addr_un->sun_path, pathname));
@ -63,18 +63,18 @@ static void test_parse_unix(const char *uri_text, const char *pathname) {
#else /* GRPC_HAVE_UNIX_SOCKET */ #else /* GRPC_HAVE_UNIX_SOCKET */
static void test_parse_unix(const char *uri_text, const char *pathname) {} static void test_grpc_parse_unix(const char *uri_text, const char *pathname) {}
#endif /* GRPC_HAVE_UNIX_SOCKET */ #endif /* GRPC_HAVE_UNIX_SOCKET */
static void test_parse_ipv4(const char *uri_text, const char *host, static void test_grpc_parse_ipv4(const char *uri_text, const char *host,
unsigned short port) { unsigned short port) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
grpc_resolved_address addr; grpc_resolved_address addr;
char ntop_buf[INET_ADDRSTRLEN]; char ntop_buf[INET_ADDRSTRLEN];
GPR_ASSERT(1 == parse_ipv4(uri, &addr)); GPR_ASSERT(1 == grpc_parse_ipv4(uri, &addr));
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr.addr; struct sockaddr_in *addr_in = (struct sockaddr_in *)addr.addr;
GPR_ASSERT(AF_INET == addr_in->sin_family); GPR_ASSERT(AF_INET == addr_in->sin_family);
GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET, &addr_in->sin_addr, ntop_buf, GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET, &addr_in->sin_addr, ntop_buf,
@ -86,14 +86,14 @@ static void test_parse_ipv4(const char *uri_text, const char *host,
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
} }
static void test_parse_ipv6(const char *uri_text, const char *host, static void test_grpc_parse_ipv6(const char *uri_text, const char *host,
unsigned short port, uint32_t scope_id) { unsigned short port, uint32_t scope_id) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
grpc_resolved_address addr; grpc_resolved_address addr;
char ntop_buf[INET6_ADDRSTRLEN]; char ntop_buf[INET6_ADDRSTRLEN];
GPR_ASSERT(1 == parse_ipv6(uri, &addr)); GPR_ASSERT(1 == grpc_parse_ipv6(uri, &addr));
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr.addr; struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr.addr;
GPR_ASSERT(AF_INET6 == addr_in6->sin6_family); GPR_ASSERT(AF_INET6 == addr_in6->sin6_family);
GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET6, &addr_in6->sin6_addr, ntop_buf, GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET6, &addr_in6->sin6_addr, ntop_buf,
@ -109,8 +109,8 @@ static void test_parse_ipv6(const char *uri_text, const char *host,
int main(int argc, char **argv) { int main(int argc, char **argv) {
grpc_test_init(argc, argv); grpc_test_init(argc, argv);
test_parse_unix("unix:/path/name", "/path/name"); test_grpc_parse_unix("unix:/path/name", "/path/name");
test_parse_ipv4("ipv4:192.0.2.1:12345", "192.0.2.1", 12345); test_grpc_parse_ipv4("ipv4:192.0.2.1:12345", "192.0.2.1", 12345);
test_parse_ipv6("ipv6:[2001:db8::1]:12345", "2001:db8::1", 12345, 0); test_grpc_parse_ipv6("ipv6:[2001:db8::1]:12345", "2001:db8::1", 12345, 0);
test_parse_ipv6("ipv6:[2001:db8::1%252]:12345", "2001:db8::1", 12345, 2); test_grpc_parse_ipv6("ipv6:[2001:db8::1%252]:12345", "2001:db8::1", 12345, 2);
} }

@ -32,20 +32,48 @@ licenses(["notice"]) # 3-clause BSD
cc_test( cc_test(
name = "dns_resolver_connectivity_test", name = "dns_resolver_connectivity_test",
srcs = ["dns_resolver_connectivity_test.c"], srcs = ["dns_resolver_connectivity_test.c"],
deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"], copts = ["-std=c99"],
copts = ['-std=c99'] deps = [
"//:gpr",
"//:grpc",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
) )
cc_test( cc_test(
name = "dns_resolver_test", name = "dns_resolver_test",
srcs = ["dns_resolver_test.c"], srcs = ["dns_resolver_test.c"],
deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"], copts = ["-std=c99"],
copts = ['-std=c99'] deps = [
"//:gpr",
"//:grpc",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
) )
cc_test( cc_test(
name = "sockaddr_resolver_test", name = "sockaddr_resolver_test",
srcs = ["sockaddr_resolver_test.c"], srcs = ["sockaddr_resolver_test.c"],
deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"], copts = ["-std=c99"],
copts = ['-std=c99'] deps = [
"//:gpr",
"//:grpc",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
)
cc_test(
name = "fake_resolver_test",
srcs = ["fake_resolver_test.c"],
copts = ["-std=c99"],
deps = [
"//:gpr",
"//:grpc",
"//test/core/end2end:fake_resolver",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],
) )

@ -0,0 +1,187 @@
/*
*
* Copyright 2017, 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 <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
#include "test/core/end2end/fake_resolver.h"
#include "test/core/util/test_config.h"
static grpc_resolver *build_fake_resolver(
grpc_exec_ctx *exec_ctx, grpc_combiner *combiner,
grpc_fake_resolver_response_generator *response_generator) {
grpc_resolver_factory *factory = grpc_resolver_factory_lookup("test");
grpc_arg generator_arg =
grpc_fake_resolver_response_generator_arg(response_generator);
grpc_resolver_args args;
memset(&args, 0, sizeof(args));
grpc_channel_args channel_args = {1, &generator_arg};
args.args = &channel_args;
args.combiner = combiner;
grpc_resolver *resolver =
grpc_resolver_factory_create_resolver(exec_ctx, factory, &args);
grpc_resolver_factory_unref(factory);
return resolver;
}
typedef struct on_resolution_arg {
grpc_channel_args *resolver_result;
grpc_channel_args *expected_resolver_result;
bool was_called;
} on_resolution_arg;
void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
on_resolution_arg *res = arg;
res->was_called = true;
// We only check the addresses channel arg because that's the only one
// explicitly set by the test via
// grpc_fake_resolver_response_generator_set_response.
const grpc_lb_addresses *actual_lb_addresses =
grpc_lb_addresses_find_channel_arg(res->resolver_result);
const grpc_lb_addresses *expected_lb_addresses =
grpc_lb_addresses_find_channel_arg(res->expected_resolver_result);
GPR_ASSERT(
grpc_lb_addresses_cmp(actual_lb_addresses, expected_lb_addresses) == 0);
grpc_channel_args_destroy(exec_ctx, res->resolver_result);
grpc_channel_args_destroy(exec_ctx, res->expected_resolver_result);
}
static void test_fake_resolver() {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_combiner *combiner = grpc_combiner_create(NULL);
// Create resolver.
grpc_fake_resolver_response_generator *response_generator =
grpc_fake_resolver_response_generator_create();
grpc_resolver *resolver =
build_fake_resolver(&exec_ctx, combiner, response_generator);
GPR_ASSERT(resolver != NULL);
// Setup expectations.
grpc_uri *uris[] = {grpc_uri_parse(&exec_ctx, "ipv4:10.2.1.1:1234", true),
grpc_uri_parse(&exec_ctx, "ipv4:127.0.0.1:4321", true)};
char *balancer_names[] = {"name1", "name2"};
const bool is_balancer[] = {true, false};
grpc_lb_addresses *addresses = grpc_lb_addresses_create(3, NULL);
for (size_t i = 0; i < GPR_ARRAY_SIZE(uris); ++i) {
grpc_lb_addresses_set_address_from_uri(
addresses, i, uris[i], is_balancer[i], balancer_names[i], NULL);
grpc_uri_destroy(uris[i]);
}
const grpc_arg addresses_arg =
grpc_lb_addresses_create_channel_arg(addresses);
grpc_channel_args *results =
grpc_channel_args_copy_and_add(NULL, &addresses_arg, 1);
grpc_lb_addresses_destroy(&exec_ctx, addresses);
on_resolution_arg on_res_arg;
memset(&on_res_arg, 0, sizeof(on_res_arg));
on_res_arg.expected_resolver_result = results;
grpc_closure *on_resolution = grpc_closure_create(
on_resolution_cb, &on_res_arg, grpc_combiner_scheduler(combiner, false));
// Set resolver results and trigger first resolution. on_resolution_cb
// performs the checks.
grpc_fake_resolver_response_generator_set_response(
&exec_ctx, response_generator, results);
grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result,
on_resolution);
grpc_exec_ctx_flush(&exec_ctx);
GPR_ASSERT(on_res_arg.was_called);
// Setup update.
grpc_uri *uris_update[] = {
grpc_uri_parse(&exec_ctx, "ipv4:192.168.1.0:31416", true)};
char *balancer_names_update[] = {"name3"};
const bool is_balancer_update[] = {false};
grpc_lb_addresses *addresses_update = grpc_lb_addresses_create(1, NULL);
for (size_t i = 0; i < GPR_ARRAY_SIZE(uris_update); ++i) {
grpc_lb_addresses_set_address_from_uri(addresses_update, i, uris_update[i],
is_balancer_update[i],
balancer_names_update[i], NULL);
grpc_uri_destroy(uris_update[i]);
}
grpc_arg addresses_update_arg =
grpc_lb_addresses_create_channel_arg(addresses_update);
grpc_channel_args *results_update =
grpc_channel_args_copy_and_add(NULL, &addresses_update_arg, 1);
grpc_lb_addresses_destroy(&exec_ctx, addresses_update);
// Setup expectations for the update.
on_resolution_arg on_res_arg_update;
memset(&on_res_arg_update, 0, sizeof(on_res_arg_update));
on_res_arg_update.expected_resolver_result = results_update;
on_resolution = grpc_closure_create(on_resolution_cb, &on_res_arg_update,
grpc_combiner_scheduler(combiner, false));
// Set updated resolver results and trigger a second resolution.
grpc_fake_resolver_response_generator_set_response(
&exec_ctx, response_generator, results_update);
grpc_resolver_next_locked(&exec_ctx, resolver,
&on_res_arg_update.resolver_result, on_resolution);
grpc_exec_ctx_flush(&exec_ctx);
GPR_ASSERT(on_res_arg.was_called);
// Requesting a new resolution without re-senting the response shouldn't
// trigger the resolution callback.
memset(&on_res_arg, 0, sizeof(on_res_arg));
grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result,
on_resolution);
grpc_exec_ctx_flush(&exec_ctx);
GPR_ASSERT(!on_res_arg.was_called);
GRPC_COMBINER_UNREF(&exec_ctx, combiner, "test_fake_resolver");
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_fake_resolver");
grpc_exec_ctx_finish(&exec_ctx);
grpc_fake_resolver_response_generator_unref(response_generator);
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_fake_resolver_init(); // Registers the "test" scheme.
grpc_init();
test_fake_resolver();
grpc_shutdown();
return 0;
}

@ -32,49 +32,66 @@ licenses(["notice"]) # 3-clause BSD
load(":generate_tests.bzl", "grpc_end2end_tests") load(":generate_tests.bzl", "grpc_end2end_tests")
cc_library( cc_library(
name = 'cq_verifier', name = "cq_verifier",
srcs = ['cq_verifier.c'], srcs = ["cq_verifier.c"],
hdrs = ['cq_verifier.h'], hdrs = ["cq_verifier.h"],
deps = ['//:gpr', '//:grpc', '//test/core/util:grpc_test_util'], copts = ["-std=c99"],
copts = ['-std=c99'], visibility = ["//test:__subpackages__"],
visibility = ["//test:__subpackages__"], deps = [
"//:gpr",
"//:grpc",
"//test/core/util:grpc_test_util",
],
) )
cc_library( cc_library(
name = 'ssl_test_data', name = "ssl_test_data",
visibility = ["//test:__subpackages__"], srcs = [
hdrs = ['data/ssl_test_data.h'], "data/client_certs.c",
copts = ['-std=c99'], "data/server1_cert.c",
srcs = [ "data/server1_key.c",
"data/client_certs.c", "data/test_root_cert.c",
"data/server1_cert.c", ],
"data/server1_key.c", hdrs = ["data/ssl_test_data.h"],
"data/test_root_cert.c", copts = ["-std=c99"],
] visibility = ["//test:__subpackages__"],
) )
cc_library( cc_library(
name = 'fake_resolver', name = "fake_resolver",
hdrs = ['fake_resolver.h'], srcs = ["fake_resolver.c"],
srcs = ['fake_resolver.c'], hdrs = ["fake_resolver.h"],
copts = ['-std=c99'], copts = ["-std=c99"],
deps = ['//:gpr', '//:grpc', '//test/core/util:grpc_test_util'] visibility = ["//test:__subpackages__"],
deps = [
"//:gpr",
"//:grpc",
"//test/core/util:grpc_test_util",
],
) )
cc_library( cc_library(
name = 'http_proxy', name = "http_proxy",
hdrs = ['fixtures/http_proxy_fixture.h'], srcs = ["fixtures/http_proxy_fixture.c"],
srcs = ['fixtures/http_proxy_fixture.c'], hdrs = ["fixtures/http_proxy_fixture.h"],
copts = ['-std=c99'], copts = ["-std=c99"],
deps = ['//:gpr', '//:grpc', '//test/core/util:grpc_test_util'] deps = [
"//:gpr",
"//:grpc",
"//test/core/util:grpc_test_util",
],
) )
cc_library( cc_library(
name = 'proxy', name = "proxy",
hdrs = ['fixtures/proxy.h'], srcs = ["fixtures/proxy.c"],
srcs = ['fixtures/proxy.c'], hdrs = ["fixtures/proxy.h"],
copts = ['-std=c99'], copts = ["-std=c99"],
deps = ['//:gpr', '//:grpc', '//test/core/util:grpc_test_util'] deps = [
"//:gpr",
"//:grpc",
"//test/core/util:grpc_test_util",
],
) )
grpc_end2end_tests() grpc_end2end_tests()

@ -32,6 +32,7 @@
// This is similar to the sockaddr resolver, except that it supports a // This is similar to the sockaddr resolver, except that it supports a
// bunch of query args that are useful for dependency injection in tests. // bunch of query args that are useful for dependency injection in tests.
#include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -46,12 +47,18 @@
#include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "test/core/end2end/fake_resolver.h"
#define GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR \
"grpc.fake_resolver.response_generator"
// //
// fake_resolver // fake_resolver
// //
@ -62,12 +69,11 @@ typedef struct {
// passed-in parameters // passed-in parameters
grpc_channel_args* channel_args; grpc_channel_args* channel_args;
grpc_lb_addresses* addresses;
// mutex guarding the rest of the state // If not NULL, the next set of resolution results to be returned to
gpr_mu mu; // grpc_resolver_next_locked()'s closure.
// have we published? grpc_channel_args* next_results;
bool published;
// pending next completion, or NULL // pending next completion, or NULL
grpc_closure* next_completion; grpc_closure* next_completion;
// target result address for next completion // target result address for next completion
@ -76,60 +82,137 @@ typedef struct {
static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) {
fake_resolver* r = (fake_resolver*)gr; fake_resolver* r = (fake_resolver*)gr;
gpr_mu_destroy(&r->mu); grpc_channel_args_destroy(exec_ctx, r->next_results);
grpc_channel_args_destroy(exec_ctx, r->channel_args); grpc_channel_args_destroy(exec_ctx, r->channel_args);
grpc_lb_addresses_destroy(exec_ctx, r->addresses);
gpr_free(r); gpr_free(r);
} }
static void fake_resolver_shutdown(grpc_exec_ctx* exec_ctx, static void fake_resolver_shutdown_locked(grpc_exec_ctx* exec_ctx,
grpc_resolver* resolver) { grpc_resolver* resolver) {
fake_resolver* r = (fake_resolver*)resolver; fake_resolver* r = (fake_resolver*)resolver;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) { if (r->next_completion != NULL) {
*r->target_result = NULL; *r->target_result = NULL;
grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE); grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
r->next_completion = NULL; r->next_completion = NULL;
} }
gpr_mu_unlock(&r->mu);
} }
static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx, static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx,
fake_resolver* r) { fake_resolver* r) {
if (r->next_completion != NULL && !r->published) { if (r->next_completion != NULL && r->next_results != NULL) {
r->published = true;
grpc_arg arg = grpc_lb_addresses_create_channel_arg(r->addresses);
*r->target_result = *r->target_result =
grpc_channel_args_copy_and_add(r->channel_args, &arg, 1); grpc_channel_args_merge(r->channel_args, r->next_results);
grpc_channel_args_destroy(exec_ctx, r->next_results);
grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE); grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
r->next_completion = NULL; r->next_completion = NULL;
r->next_results = NULL;
} }
} }
static void fake_resolver_channel_saw_error(grpc_exec_ctx* exec_ctx, static void fake_resolver_channel_saw_error_locked(grpc_exec_ctx* exec_ctx,
grpc_resolver* resolver) { grpc_resolver* resolver) {
fake_resolver* r = (fake_resolver*)resolver; fake_resolver* r = (fake_resolver*)resolver;
gpr_mu_lock(&r->mu);
r->published = false;
fake_resolver_maybe_finish_next_locked(exec_ctx, r); fake_resolver_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
} }
static void fake_resolver_next(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver, static void fake_resolver_next_locked(grpc_exec_ctx* exec_ctx,
grpc_channel_args** target_result, grpc_resolver* resolver,
grpc_closure* on_complete) { grpc_channel_args** target_result,
grpc_closure* on_complete) {
fake_resolver* r = (fake_resolver*)resolver; fake_resolver* r = (fake_resolver*)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion); GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete; r->next_completion = on_complete;
r->target_result = target_result; r->target_result = target_result;
fake_resolver_maybe_finish_next_locked(exec_ctx, r); fake_resolver_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
} }
static const grpc_resolver_vtable fake_resolver_vtable = { static const grpc_resolver_vtable fake_resolver_vtable = {
fake_resolver_destroy, fake_resolver_shutdown, fake_resolver_destroy, fake_resolver_shutdown_locked,
fake_resolver_channel_saw_error, fake_resolver_next}; fake_resolver_channel_saw_error_locked, fake_resolver_next_locked};
struct grpc_fake_resolver_response_generator {
fake_resolver* resolver; // Set by the fake_resolver constructor to itself.
grpc_channel_args* next_response;
gpr_refcount refcount;
};
grpc_fake_resolver_response_generator*
grpc_fake_resolver_response_generator_create() {
grpc_fake_resolver_response_generator* generator =
gpr_zalloc(sizeof(*generator));
gpr_ref_init(&generator->refcount, 1);
return generator;
}
grpc_fake_resolver_response_generator*
grpc_fake_resolver_response_generator_ref(
grpc_fake_resolver_response_generator* generator) {
gpr_ref(&generator->refcount);
return generator;
}
void grpc_fake_resolver_response_generator_unref(
grpc_fake_resolver_response_generator* generator) {
if (gpr_unref(&generator->refcount)) {
gpr_free(generator);
}
}
static void set_response_cb(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
grpc_fake_resolver_response_generator* generator = arg;
fake_resolver* r = generator->resolver;
if (r->next_results != NULL) {
grpc_channel_args_destroy(exec_ctx, r->next_results);
}
r->next_results = generator->next_response;
fake_resolver_maybe_finish_next_locked(exec_ctx, r);
}
void grpc_fake_resolver_response_generator_set_response(
grpc_exec_ctx* exec_ctx, grpc_fake_resolver_response_generator* generator,
grpc_channel_args* next_response) {
GPR_ASSERT(generator->resolver != NULL);
generator->next_response = grpc_channel_args_copy(next_response);
grpc_closure_sched(
exec_ctx,
grpc_closure_create(
set_response_cb, generator,
grpc_combiner_scheduler(generator->resolver->base.combiner, false)),
GRPC_ERROR_NONE);
}
static void* response_generator_arg_copy(void* p) {
return grpc_fake_resolver_response_generator_ref(p);
}
static void response_generator_arg_destroy(grpc_exec_ctx* exec_ctx, void* p) {
grpc_fake_resolver_response_generator_unref(p);
}
static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
response_generator_arg_copy, response_generator_arg_destroy,
response_generator_cmp};
grpc_arg grpc_fake_resolver_response_generator_arg(
grpc_fake_resolver_response_generator* generator) {
grpc_arg arg;
arg.type = GRPC_ARG_POINTER;
arg.key = GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
arg.value.pointer.p = generator;
arg.value.pointer.vtable = &response_generator_arg_vtable;
return arg;
}
grpc_fake_resolver_response_generator*
grpc_fake_resolver_get_response_generator(const grpc_channel_args* args) {
const grpc_arg* arg =
grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
if (arg == NULL || arg->type != GRPC_ARG_POINTER) return NULL;
return arg->value.pointer.p;
}
// //
// fake_resolver_factory // fake_resolver_factory
@ -139,81 +222,15 @@ static void fake_resolver_factory_ref(grpc_resolver_factory* factory) {}
static void fake_resolver_factory_unref(grpc_resolver_factory* factory) {} static void fake_resolver_factory_unref(grpc_resolver_factory* factory) {}
static void do_nothing(void* ignored) {}
static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx, static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx,
grpc_resolver_factory* factory, grpc_resolver_factory* factory,
grpc_resolver_args* args) { grpc_resolver_args* args) {
if (0 != strcmp(args->uri->authority, "")) { fake_resolver* r = gpr_zalloc(sizeof(*r));
gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme",
args->uri->scheme);
return NULL;
}
// Get lb_enabled arg. Anything other than "0" is interpreted as true.
const char* lb_enabled_qpart =
grpc_uri_get_query_arg(args->uri, "lb_enabled");
const bool lb_enabled =
lb_enabled_qpart != NULL && strcmp("0", lb_enabled_qpart) != 0;
// Get the balancer's names.
const char* balancer_names =
grpc_uri_get_query_arg(args->uri, "balancer_names");
grpc_slice_buffer balancer_names_parts;
grpc_slice_buffer_init(&balancer_names_parts);
if (balancer_names != NULL) {
const grpc_slice balancer_names_slice =
grpc_slice_from_copied_string(balancer_names);
grpc_slice_split(balancer_names_slice, ",", &balancer_names_parts);
grpc_slice_unref(balancer_names_slice);
}
// Construct addresses.
grpc_slice path_slice =
grpc_slice_new(args->uri->path, strlen(args->uri->path), do_nothing);
grpc_slice_buffer path_parts;
grpc_slice_buffer_init(&path_parts);
grpc_slice_split(path_slice, ",", &path_parts);
if (balancer_names_parts.count > 0 &&
path_parts.count != balancer_names_parts.count) {
gpr_log(GPR_ERROR,
"Balancer names present but mismatched with number of addresses: "
"%lu balancer names != %lu addresses",
(unsigned long)balancer_names_parts.count,
(unsigned long)path_parts.count);
return NULL;
}
grpc_lb_addresses* addresses =
grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */);
bool errors_found = false;
for (size_t i = 0; i < addresses->num_addresses; i++) {
grpc_uri ith_uri = *args->uri;
char* part_str = grpc_slice_to_c_string(path_parts.slices[i]);
ith_uri.path = part_str;
if (!parse_ipv4(&ith_uri, &addresses->addresses[i].address)) {
errors_found = true;
}
gpr_free(part_str);
if (errors_found) break;
addresses->addresses[i].is_balancer = lb_enabled;
addresses->addresses[i].balancer_name =
balancer_names_parts.count > 0
? grpc_dump_slice(balancer_names_parts.slices[i], GPR_DUMP_ASCII)
: NULL;
}
grpc_slice_buffer_destroy_internal(exec_ctx, &path_parts);
grpc_slice_buffer_destroy_internal(exec_ctx, &balancer_names_parts);
grpc_slice_unref(path_slice);
if (errors_found) {
grpc_lb_addresses_destroy(exec_ctx, addresses);
return NULL;
}
// Instantiate resolver.
fake_resolver* r = gpr_malloc(sizeof(fake_resolver));
memset(r, 0, sizeof(*r));
r->channel_args = grpc_channel_args_copy(args->args); r->channel_args = grpc_channel_args_copy(args->args);
r->addresses = addresses;
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &fake_resolver_vtable, args->combiner); grpc_resolver_init(&r->base, &fake_resolver_vtable, args->combiner);
grpc_fake_resolver_response_generator* response_generator =
grpc_fake_resolver_get_response_generator(args->args);
if (response_generator != NULL) response_generator->resolver = r;
return &r->base; return &r->base;
} }

@ -32,8 +32,42 @@
#ifndef GRPC_TEST_CORE_END2END_FAKE_RESOLVER_H #ifndef GRPC_TEST_CORE_END2END_FAKE_RESOLVER_H
#define GRPC_TEST_CORE_END2END_FAKE_RESOLVER_H #define GRPC_TEST_CORE_END2END_FAKE_RESOLVER_H
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/ext/filters/client_channel/uri_parser.h"
#include "src/core/lib/channel/channel_args.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
void grpc_fake_resolver_init(); void grpc_fake_resolver_init();
// Instances of \a grpc_fake_resolver_response_generator are passed to the
// fake resolver in a channel argument (see \a
// grpc_fake_resolver_response_generator_arg) in order to inject and trigger
// custom resolutions. See also \a
// grpc_fake_resolver_response_generator_set_response.
typedef struct grpc_fake_resolver_response_generator
grpc_fake_resolver_response_generator;
grpc_fake_resolver_response_generator*
grpc_fake_resolver_response_generator_create();
// Instruct the fake resolver associated with the \a response_generator instance
// to trigger a new resolution for \a uri and \a args.
void grpc_fake_resolver_response_generator_set_response(
grpc_exec_ctx* exec_ctx, grpc_fake_resolver_response_generator* generator,
grpc_channel_args* next_response);
// Return a \a grpc_arg for a \a grpc_fake_resolver_response_generator instance.
grpc_arg grpc_fake_resolver_response_generator_arg(
grpc_fake_resolver_response_generator* generator);
// Return the \a grpc_fake_resolver_response_generator instance in \a args or
// NULL.
grpc_fake_resolver_response_generator*
grpc_fake_resolver_get_response_generator(const grpc_channel_args* args);
grpc_fake_resolver_response_generator*
grpc_fake_resolver_response_generator_ref(
grpc_fake_resolver_response_generator* generator);
void grpc_fake_resolver_response_generator_unref(
grpc_fake_resolver_response_generator* generator);
#endif /* GRPC_TEST_CORE_END2END_FAKE_RESOLVER_H */ #endif /* GRPC_TEST_CORE_END2END_FAKE_RESOLVER_H */

@ -573,34 +573,51 @@ static void perform_request(client_fixture *cf) {
static void setup_client(const server_fixture *lb_server, static void setup_client(const server_fixture *lb_server,
const server_fixture *backends, client_fixture *cf) { const server_fixture *backends, client_fixture *cf) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
char *lb_uri;
// The grpclb LB policy will be automatically selected by virtue of
// the fact that the returned addresses are balancer addresses.
gpr_asprintf(&lb_uri, "test:///%s?lb_enabled=1&balancer_names=%s",
lb_server->servers_hostport, lb_server->balancer_name);
grpc_arg expected_target_arg;
expected_target_arg.type = GRPC_ARG_STRING;
expected_target_arg.key =
const_cast<char *>(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS);
char *expected_target_names = NULL; char *expected_target_names = NULL;
const char *backends_name = lb_server->servers_hostport; const char *backends_name = lb_server->servers_hostport;
gpr_asprintf(&expected_target_names, "%s;%s", backends_name, BALANCERS_NAME); gpr_asprintf(&expected_target_names, "%s;%s", backends_name, BALANCERS_NAME);
expected_target_arg.value.string = const_cast<char *>(expected_target_names); grpc_fake_resolver_response_generator *response_generator =
grpc_fake_resolver_response_generator_create();
grpc_lb_addresses *addresses = grpc_lb_addresses_create(1, NULL);
char *lb_uri_str;
gpr_asprintf(&lb_uri_str, "ipv4:%s", lb_server->servers_hostport);
grpc_uri *lb_uri = grpc_uri_parse(&exec_ctx, lb_uri_str, true);
GPR_ASSERT(lb_uri != NULL);
grpc_lb_addresses_set_address_from_uri(addresses, 0, lb_uri, true,
lb_server->balancer_name, NULL);
grpc_uri_destroy(lb_uri);
gpr_free(lb_uri_str);
gpr_asprintf(&cf->server_uri, "test:///%s", lb_server->servers_hostport);
const grpc_arg fake_addresses =
grpc_lb_addresses_create_channel_arg(addresses);
grpc_channel_args *fake_result =
grpc_channel_args_copy_and_add(NULL, &fake_addresses, 1);
grpc_lb_addresses_destroy(&exec_ctx, addresses);
const grpc_arg new_args[] = {
grpc_fake_transport_expected_targets_arg(expected_target_names),
grpc_fake_resolver_response_generator_arg(response_generator)};
grpc_channel_args *args = grpc_channel_args *args =
grpc_channel_args_copy_and_add(NULL, &expected_target_arg, 1); grpc_channel_args_copy_and_add(NULL, new_args, GPR_ARRAY_SIZE(new_args));
gpr_free(expected_target_names); gpr_free(expected_target_names);
cf->cq = grpc_completion_queue_create_for_next(NULL); cf->cq = grpc_completion_queue_create_for_next(NULL);
cf->server_uri = lb_uri;
grpc_channel_credentials *fake_creds = grpc_channel_credentials *fake_creds =
grpc_fake_transport_security_credentials_create(); grpc_fake_transport_security_credentials_create();
cf->client = cf->client =
grpc_secure_channel_create(fake_creds, cf->server_uri, args, NULL); grpc_secure_channel_create(fake_creds, cf->server_uri, args, NULL);
grpc_fake_resolver_response_generator_set_response(
&exec_ctx, response_generator, fake_result);
grpc_channel_args_destroy(&exec_ctx, fake_result);
grpc_channel_credentials_unref(&exec_ctx, fake_creds); grpc_channel_credentials_unref(&exec_ctx, fake_creds);
grpc_channel_args_destroy(&exec_ctx, args); grpc_channel_args_destroy(&exec_ctx, args);
grpc_fake_resolver_response_generator_unref(response_generator);
grpc_exec_ctx_finish(&exec_ctx);
} }
static void teardown_client(client_fixture *cf) { static void teardown_client(client_fixture *cf) {
@ -787,8 +804,8 @@ TEST(GrpclbTest, InvalidAddressInServerlist) {}
int main(int argc, char **argv) { int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
grpc_test_init(argc, argv);
grpc_fake_resolver_init(); grpc_fake_resolver_init();
grpc_test_init(argc, argv);
grpc_init(); grpc_init();
const auto result = RUN_ALL_TESTS(); const auto result = RUN_ALL_TESTS();
grpc_shutdown(); grpc_shutdown();

@ -470,6 +470,23 @@
"third_party": false, "third_party": false,
"type": "target" "type": "target"
}, },
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "fake_resolver_test",
"src": [
"test/core/client_channel/resolvers/fake_resolver_test.c"
],
"third_party": false,
"type": "target"
},
{ {
"deps": [ "deps": [
"gpr", "gpr",

@ -577,6 +577,28 @@
"linux" "linux"
] ]
}, },
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "fake_resolver_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{ {
"args": [], "args": [],
"ci_platforms": [ "ci_platforms": [

@ -317,6 +317,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "error_test", "vcxproj\test\
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fake_resolver_test", "vcxproj\test\fake_resolver_test\fake_resolver_test.vcxproj", "{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}"
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}") = "fling_client", "vcxproj\test\fling_client\fling_client.vcxproj", "{0647D598-9611-F659-EA36-DF995C9F736B}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fling_client", "vcxproj\test\fling_client\fling_client.vcxproj", "{0647D598-9611-F659-EA36-DF995C9F736B}"
ProjectSection(myProperties) = preProject ProjectSection(myProperties) = preProject
lib = "False" lib = "False"
@ -2116,6 +2127,22 @@ Global
{42720233-A6D4-66BC-CCA2-06B57261D0B3}.Release-DLL|Win32.Build.0 = Release|Win32 {42720233-A6D4-66BC-CCA2-06B57261D0B3}.Release-DLL|Win32.Build.0 = Release|Win32
{42720233-A6D4-66BC-CCA2-06B57261D0B3}.Release-DLL|x64.ActiveCfg = Release|x64 {42720233-A6D4-66BC-CCA2-06B57261D0B3}.Release-DLL|x64.ActiveCfg = Release|x64
{42720233-A6D4-66BC-CCA2-06B57261D0B3}.Release-DLL|x64.Build.0 = Release|x64 {42720233-A6D4-66BC-CCA2-06B57261D0B3}.Release-DLL|x64.Build.0 = Release|x64
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Debug|Win32.ActiveCfg = Debug|Win32
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Debug|x64.ActiveCfg = Debug|x64
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Release|Win32.ActiveCfg = Release|Win32
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Release|x64.ActiveCfg = Release|x64
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Debug|Win32.Build.0 = Debug|Win32
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Debug|x64.Build.0 = Debug|x64
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Release|Win32.Build.0 = Release|Win32
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Release|x64.Build.0 = Release|x64
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Debug-DLL|Win32.Build.0 = Debug|Win32
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Debug-DLL|x64.ActiveCfg = Debug|x64
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Debug-DLL|x64.Build.0 = Debug|x64
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Release-DLL|Win32.ActiveCfg = Release|Win32
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Release-DLL|Win32.Build.0 = Release|Win32
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Release-DLL|x64.ActiveCfg = Release|x64
{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}.Release-DLL|x64.Build.0 = Release|x64
{0647D598-9611-F659-EA36-DF995C9F736B}.Debug|Win32.ActiveCfg = Debug|Win32 {0647D598-9611-F659-EA36-DF995C9F736B}.Debug|Win32.ActiveCfg = Debug|Win32
{0647D598-9611-F659-EA36-DF995C9F736B}.Debug|x64.ActiveCfg = Debug|x64 {0647D598-9611-F659-EA36-DF995C9F736B}.Debug|x64.ActiveCfg = Debug|x64
{0647D598-9611-F659-EA36-DF995C9F736B}.Release|Win32.ActiveCfg = Release|Win32 {0647D598-9611-F659-EA36-DF995C9F736B}.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>{2F59EB2E-CEF9-A291-9480-1F737C3E5E57}</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>fake_resolver_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>fake_resolver_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_channel\resolvers\fake_resolver_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_channel\resolvers\fake_resolver_test.c">
<Filter>test\core\client_channel\resolvers</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="test">
<UniqueIdentifier>{05f58640-4b7c-c233-bf86-f119fe270ba1}</UniqueIdentifier>
</Filter>
<Filter Include="test\core">
<UniqueIdentifier>{caeef88d-baf6-603c-83b0-84b1009be480}</UniqueIdentifier>
</Filter>
<Filter Include="test\core\client_channel">
<UniqueIdentifier>{c5bba556-fd85-f7b4-99b7-8b1eeb4dfcb2}</UniqueIdentifier>
</Filter>
<Filter Include="test\core\client_channel\resolvers">
<UniqueIdentifier>{eff74a86-6a4c-b68c-0330-6901d992c5c7}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
Loading…
Cancel
Save