aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/grpc/support/slice_buffer.h3
-rw-r--r--src/core/iomgr/iomgr.c7
-rw-r--r--src/core/iomgr/pollset_multipoller_with_epoll.c25
-rw-r--r--src/core/iomgr/pollset_multipoller_with_poll_posix.c22
-rw-r--r--src/core/iomgr/pollset_posix.c50
-rw-r--r--src/core/iomgr/pollset_posix.h1
-rw-r--r--src/core/iomgr/pollset_windows.c4
-rw-r--r--test/core/end2end/README2
-rw-r--r--test/core/end2end/tests/channel_connectivity.c56
-rw-r--r--test/core/util/test_config.c34
-rw-r--r--test/cpp/end2end/end2end_test.cc834
-rw-r--r--vsprojects/coapp/zlib/README.md35
-rw-r--r--vsprojects/coapp/zlib/buildall.bat51
-rw-r--r--vsprojects/coapp/zlib/grpc.dependencies.zlib.autopkg102
-rw-r--r--vsprojects/coapp/zlib/managed_targets/grpc.dependencies.zlib.redist.props13
-rw-r--r--vsprojects/coapp/zlib/managed_targets/grpc.dependencies.zlib.redist.targets14
-rw-r--r--vsprojects/coapp/zlib/version.inc1
-rw-r--r--vsprojects/coapp/zlib/zlib.sln26
-rw-r--r--vsprojects/coapp/zlib/zlib.vcxproj147
19 files changed, 977 insertions, 450 deletions
diff --git a/include/grpc/support/slice_buffer.h b/include/grpc/support/slice_buffer.h
index f3f14a6aa0..e4f296c32a 100644
--- a/include/grpc/support/slice_buffer.h
+++ b/include/grpc/support/slice_buffer.h
@@ -87,7 +87,8 @@ void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b);
/* move all of the elements of src into dst */
void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst);
/* remove n bytes from the end of a slice buffer */
-void gpr_slice_buffer_trim_end(gpr_slice_buffer *src, size_t n, gpr_slice_buffer *garbage);
+void gpr_slice_buffer_trim_end(gpr_slice_buffer *src, size_t n,
+ gpr_slice_buffer *garbage);
#ifdef __cplusplus
}
diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c
index a10399311f..e61fc32925 100644
--- a/src/core/iomgr/iomgr.c
+++ b/src/core/iomgr/iomgr.c
@@ -51,13 +51,6 @@ static gpr_cv g_rcv;
static int g_shutdown;
static grpc_iomgr_object g_root_object;
-void grpc_kick_poller(void) {
- /* Empty. The background callback executor polls periodically. The activity
- * the kicker is trying to draw the executor's attention to will be picked up
- * either by one of the periodic wakeups or by one of the polling application
- * threads. */
-}
-
void grpc_iomgr_init(void) {
g_shutdown = 0;
gpr_mu_init(&g_mu);
diff --git a/src/core/iomgr/pollset_multipoller_with_epoll.c b/src/core/iomgr/pollset_multipoller_with_epoll.c
index b22eaa6288..d26e60f665 100644
--- a/src/core/iomgr/pollset_multipoller_with_epoll.c
+++ b/src/core/iomgr/pollset_multipoller_with_epoll.c
@@ -213,11 +213,15 @@ static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
int cancel = ep_ev[i].events & (EPOLLERR | EPOLLHUP);
int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI);
int write_ev = ep_ev[i].events & EPOLLOUT;
- if (read_ev || cancel) {
- grpc_fd_become_readable(exec_ctx, fd);
- }
- if (write_ev || cancel) {
- grpc_fd_become_writable(exec_ctx, fd);
+ if (fd == NULL) {
+ grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
+ } else {
+ if (read_ev || cancel) {
+ grpc_fd_become_readable(exec_ctx, fd);
+ }
+ if (write_ev || cancel) {
+ grpc_fd_become_writable(exec_ctx, fd);
+ }
}
}
}
@@ -246,6 +250,8 @@ static void epoll_become_multipoller(grpc_exec_ctx *exec_ctx,
size_t nfds) {
size_t i;
pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr));
+ struct epoll_event ev;
+ int err;
pollset->vtable = &multipoll_with_epoll_pollset;
pollset->data.ptr = h;
@@ -255,6 +261,15 @@ static void epoll_become_multipoller(grpc_exec_ctx *exec_ctx,
gpr_log(GPR_ERROR, "epoll_create1 failed: %s", strerror(errno));
abort();
}
+
+ ev.events = (uint32_t)(EPOLLIN | EPOLLET);
+ ev.data.ptr = NULL;
+ err = epoll_ctl(h->epoll_fd, EPOLL_CTL_ADD, GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd), &ev);
+ if (err < 0) {
+ gpr_log(GPR_ERROR, "epoll_ctl add for %d failed: %s", GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd),
+ strerror(errno));
+ }
+
for (i = 0; i < nfds; i++) {
multipoll_with_epoll_pollset_add_fd(exec_ctx, pollset, fds[i], 0);
}
diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c
index 63e0b9edb9..1356ebe7a0 100644
--- a/src/core/iomgr/pollset_multipoller_with_poll_posix.c
+++ b/src/core/iomgr/pollset_multipoller_with_poll_posix.c
@@ -114,13 +114,16 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
h = pollset->data.ptr;
timeout = grpc_poll_deadline_to_millis_timeout(deadline, now);
/* TODO(ctiller): perform just one malloc here if we exceed the inline case */
- pfds = gpr_malloc(sizeof(*pfds) * (h->fd_count + 1));
- watchers = gpr_malloc(sizeof(*watchers) * (h->fd_count + 1));
+ pfds = gpr_malloc(sizeof(*pfds) * (h->fd_count + 2));
+ watchers = gpr_malloc(sizeof(*watchers) * (h->fd_count + 2));
fd_count = 0;
- pfd_count = 1;
- pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd);
+ pfd_count = 2;
+ pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd);
pfds[0].events = POLLIN;
- pfds[0].revents = POLLOUT;
+ pfds[0].revents = 0;
+ pfds[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd);
+ pfds[1].events = POLLIN;
+ pfds[1].revents = 0;
for (i = 0; i < h->fd_count; i++) {
int remove = grpc_fd_is_orphaned(h->fds[i]);
for (j = 0; !remove && j < h->del_count; j++) {
@@ -143,7 +146,7 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
h->fd_count = fd_count;
gpr_mu_unlock(&pollset->mu);
- for (i = 1; i < pfd_count; i++) {
+ for (i = 2; i < pfd_count; i++) {
pfds[i].events = (short)grpc_fd_begin_poll(watchers[i].fd, pollset, POLLIN,
POLLOUT, &watchers[i]);
}
@@ -154,7 +157,7 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
r = grpc_poll_function(pfds, pfd_count, timeout);
GRPC_SCHEDULING_END_BLOCKING_REGION;
- for (i = 1; i < pfd_count; i++) {
+ for (i = 2; i < pfd_count; i++) {
grpc_fd_end_poll(exec_ctx, &watchers[i], pfds[i].revents & POLLIN,
pfds[i].revents & POLLOUT);
}
@@ -167,9 +170,12 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
/* do nothing */
} else {
if (pfds[0].revents & POLLIN) {
+ grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
+ }
+ if (pfds[1].revents & POLLIN) {
grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd);
}
- for (i = 1; i < pfd_count; i++) {
+ for (i = 2; i < pfd_count; i++) {
if (watchers[i].fd == NULL) {
continue;
}
diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c
index f9d6aad651..82a82cc064 100644
--- a/src/core/iomgr/pollset_posix.c
+++ b/src/core/iomgr/pollset_posix.c
@@ -57,8 +57,16 @@
GPR_TLS_DECL(g_current_thread_poller);
GPR_TLS_DECL(g_current_thread_worker);
+/** Default poll() function - a pointer so that it can be overridden by some
+ * tests */
grpc_poll_function_type grpc_poll_function = poll;
+/** The alarm system needs to be able to wakeup 'some poller' sometimes
+ * (specifically when a new alarm needs to be triggered earlier than the next
+ * alarm 'epoch').
+ * This wakeup_fd gives us something to alert on when such a case occurs. */
+grpc_wakeup_fd grpc_global_wakeup_fd;
+
static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
worker->prev->next = worker->next;
worker->next->prev = worker->prev;
@@ -121,12 +129,18 @@ void grpc_pollset_global_init(void) {
gpr_tls_init(&g_current_thread_poller);
gpr_tls_init(&g_current_thread_worker);
grpc_wakeup_fd_global_init();
+ grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
}
void grpc_pollset_global_shutdown(void) {
+ grpc_wakeup_fd_destroy(&grpc_global_wakeup_fd);
+ grpc_wakeup_fd_global_destroy();
gpr_tls_destroy(&g_current_thread_poller);
gpr_tls_destroy(&g_current_thread_worker);
- grpc_wakeup_fd_global_destroy();
+}
+
+void grpc_kick_poller(void) {
+ grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd);
}
/* main interface */
@@ -193,6 +207,8 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
goto done;
}
if (grpc_alarm_check(exec_ctx, now, &deadline)) {
+ gpr_mu_unlock(&pollset->mu);
+ locked = 0;
goto done;
}
if (pollset->shutting_down) {
@@ -294,7 +310,7 @@ int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline,
}
timeout = gpr_time_sub(deadline, now);
return gpr_time_to_millis(gpr_time_add(
- timeout, gpr_time_from_nanos(GPR_NS_PER_SEC - 1, GPR_TIMESPAN)));
+ timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
}
/*
@@ -439,7 +455,7 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
grpc_pollset_worker *worker,
gpr_timespec deadline,
gpr_timespec now) {
- struct pollfd pfd[2];
+ struct pollfd pfd[3];
grpc_fd *fd;
grpc_fd_watcher fd_watcher;
int timeout;
@@ -452,17 +468,20 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
fd = pollset->data.ptr = NULL;
}
timeout = grpc_poll_deadline_to_millis_timeout(deadline, now);
- pfd[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd);
+ pfd[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd);
pfd[0].events = POLLIN;
pfd[0].revents = 0;
- nfds = 1;
+ pfd[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd);
+ pfd[1].events = POLLIN;
+ pfd[1].revents = 0;
+ nfds = 2;
if (fd) {
- pfd[1].fd = fd->fd;
- pfd[1].revents = 0;
+ pfd[2].fd = fd->fd;
+ pfd[2].revents = 0;
gpr_mu_unlock(&pollset->mu);
- pfd[1].events =
+ pfd[2].events =
(short)grpc_fd_begin_poll(fd, pollset, POLLIN, POLLOUT, &fd_watcher);
- if (pfd[1].events != 0) {
+ if (pfd[2].events != 0) {
nfds++;
}
} else {
@@ -479,8 +498,8 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
GRPC_TIMER_MARK(GRPC_PTAG_POLL_FINISHED, r);
if (fd) {
- grpc_fd_end_poll(exec_ctx, &fd_watcher, pfd[1].revents & POLLIN,
- pfd[1].revents & POLLOUT);
+ grpc_fd_end_poll(exec_ctx, &fd_watcher, pfd[2].revents & POLLIN,
+ pfd[2].revents & POLLOUT);
}
if (r < 0) {
@@ -491,13 +510,16 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
/* do nothing */
} else {
if (pfd[0].revents & POLLIN) {
+ grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
+ }
+ if (pfd[1].revents & POLLIN) {
grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd);
}
- if (nfds > 1) {
- if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
+ if (nfds > 2) {
+ if (pfd[2].revents & (POLLIN | POLLHUP | POLLERR)) {
grpc_fd_become_readable(exec_ctx, fd);
}
- if (pfd[1].revents & (POLLOUT | POLLHUP | POLLERR)) {
+ if (pfd[2].revents & (POLLOUT | POLLHUP | POLLERR)) {
grpc_fd_become_writable(exec_ctx, fd);
}
}
diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h
index f996dd1edf..83c5258539 100644
--- a/src/core/iomgr/pollset_posix.h
+++ b/src/core/iomgr/pollset_posix.h
@@ -129,5 +129,6 @@ int grpc_pollset_has_workers(grpc_pollset *pollset);
/* override to allow tests to hook poll() usage */
typedef int (*grpc_poll_function_type)(struct pollfd *, nfds_t, int);
extern grpc_poll_function_type grpc_poll_function;
+extern grpc_wakeup_fd grpc_global_wakeup_fd;
#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_POSIX_H */
diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c
index 798b637635..1b4935a841 100644
--- a/src/core/iomgr/pollset_windows.c
+++ b/src/core/iomgr/pollset_windows.c
@@ -230,4 +230,8 @@ void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
}
}
+void grpc_kick_poller(void) {
+ grpc_iocp_kick();
+}
+
#endif /* GPR_WINSOCK_SOCKET */
diff --git a/test/core/end2end/README b/test/core/end2end/README
index 59daec45d0..a18172a7a1 100644
--- a/test/core/end2end/README
+++ b/test/core/end2end/README
@@ -3,5 +3,5 @@ forms a complete end-to-end test.
To add a new test or fixture:
- add the code to the relevant directory
-- update gen_build_json.py to reflect the change
+- update gen_build_yaml.py to reflect the change
- regenerate projects
diff --git a/test/core/end2end/tests/channel_connectivity.c b/test/core/end2end/tests/channel_connectivity.c
index 0b7a8a664b..be9b7fde1d 100644
--- a/test/core/end2end/tests/channel_connectivity.c
+++ b/test/core/end2end/tests/channel_connectivity.c
@@ -34,19 +34,49 @@
#include "test/core/end2end/end2end_tests.h"
#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
#include <grpc/support/time.h>
#include "test/core/end2end/cq_verifier.h"
static void *tag(gpr_intptr t) { return (void *)t; }
+typedef struct {
+ gpr_event started;
+ grpc_channel *channel;
+ grpc_completion_queue *cq;
+} child_events;
+
+static void child_thread(void *arg) {
+ child_events *ce = arg;
+ grpc_event ev;
+ gpr_event_set(&ce->started, (void*)1);
+ gpr_log(GPR_DEBUG, "verifying");
+ ev = grpc_completion_queue_next(ce->cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL);
+ GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+ GPR_ASSERT(ev.tag == tag(1));
+ GPR_ASSERT(ev.success == 0);
+}
+
static void test_connectivity(grpc_end2end_test_config config) {
grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL);
grpc_connectivity_state state;
cq_verifier *cqv = cq_verifier_create(f.cq);
+ child_events ce;
+ gpr_thd_options thdopt = gpr_thd_options_default();
+ gpr_thd_id thdid;
config.init_client(&f, NULL);
+ ce.channel = f.client;
+ ce.cq = f.cq;
+ gpr_event_init(&ce.started);
+ gpr_thd_options_set_joinable(&thdopt);
+ GPR_ASSERT(gpr_thd_new(&thdid, child_thread, &ce, &thdopt));
+
+ gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC));
+
/* channels should start life in IDLE, and stay there */
GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) ==
GRPC_CHANNEL_IDLE);
@@ -55,18 +85,24 @@ static void test_connectivity(grpc_end2end_test_config config) {
GRPC_CHANNEL_IDLE);
/* start watching for a change */
+ gpr_log(GPR_DEBUG, "watching");
grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_IDLE,
- GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
+ gpr_now(GPR_CLOCK_MONOTONIC),
f.cq, tag(1));
- /* nothing should happen */
- cq_verify_empty(cqv);
+
+ /* eventually the child thread completion should trigger */
+ gpr_thd_join(thdid);
/* check that we're still in idle, and start connecting */
GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) ==
GRPC_CHANNEL_IDLE);
+ /* start watching for a change */
+ grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_IDLE,
+ GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
+ f.cq, tag(2));
/* and now the watch should trigger */
- cq_expect_completion(cqv, tag(1), 1);
+ cq_expect_completion(cqv, tag(2), 1);
cq_verify(cqv);
state = grpc_channel_check_connectivity_state(f.client, 0);
GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
@@ -75,8 +111,8 @@ static void test_connectivity(grpc_end2end_test_config config) {
/* quickly followed by a transition to TRANSIENT_FAILURE */
grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_CONNECTING,
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
- f.cq, tag(2));
- cq_expect_completion(cqv, tag(2), 1);
+ f.cq, tag(3));
+ cq_expect_completion(cqv, tag(3), 1);
cq_verify(cqv);
state = grpc_channel_check_connectivity_state(f.client, 0);
GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
@@ -93,8 +129,8 @@ static void test_connectivity(grpc_end2end_test_config config) {
READY is reached */
while (state != GRPC_CHANNEL_READY) {
grpc_channel_watch_connectivity_state(
- f.client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(3));
- cq_expect_completion(cqv, tag(3), 1);
+ f.client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(4));
+ cq_expect_completion(cqv, tag(4), 1);
cq_verify(cqv);
state = grpc_channel_check_connectivity_state(f.client, 0);
GPR_ASSERT(state == GRPC_CHANNEL_READY ||
@@ -108,11 +144,11 @@ static void test_connectivity(grpc_end2end_test_config config) {
grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_READY,
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
- f.cq, tag(4));
+ f.cq, tag(5));
grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead));
- cq_expect_completion(cqv, tag(4), 1);
+ cq_expect_completion(cqv, tag(5), 1);
cq_expect_completion(cqv, tag(0xdead), 1);
cq_verify(cqv);
state = grpc_channel_check_connectivity_state(f.client, 0);
diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c
index 30caf4b1ef..84b376ad3e 100644
--- a/test/core/util/test_config.c
+++ b/test/core/util/test_config.c
@@ -35,6 +35,7 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/log.h>
+#include "src/core/support/string.h"
#include <stdlib.h>
#include <signal.h>
@@ -88,25 +89,43 @@ static void install_crash_handler() {
#include <stdio.h>
#include <string.h>
#include <grpc/support/useful.h>
+#include <errno.h>
static char g_alt_stack[MINSIGSTKSZ];
#define MAX_FRAMES 32
+/* signal safe output */
+static void output_string(const char *string) {
+ size_t len = strlen(string);
+ ssize_t r;
+
+ do {
+ r = write(STDERR_FILENO, string, len);
+ } while (r == -1 && errno == EINTR);
+}
+
+static void output_num(long num) {
+ char buf[GPR_LTOA_MIN_BUFSIZE];
+ gpr_ltoa(num, buf);
+ output_string(buf);
+}
+
static void crash_handler(int signum, siginfo_t *info, void *data) {
void *addrlist[MAX_FRAMES + 1];
int addrlen;
- int i;
- char **symlist;
- fprintf(stderr, "Caught signal %d\n", signum);
+ output_string("\n\n\n*******************************\nCaught signal ");
+ output_num(signum);
+ output_string("\n");
+
addrlen = backtrace(addrlist, GPR_ARRAY_SIZE(addrlist));
- symlist = backtrace_symbols(addrlist, addrlen);
- for (i = 0; i < addrlen; i++) {
- fprintf(stderr, " %s\n", symlist[i]);
+ if (addrlen == 0) {
+ output_string(" no backtrace\n");
+ } else {
+ backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO);
}
- free(symlist);
raise(signum);
}
@@ -114,6 +133,7 @@ static void crash_handler(int signum, siginfo_t *info, void *data) {
static void install_crash_handler() {
stack_t ss;
struct sigaction sa;
+
memset(&ss, 0, sizeof(ss));
memset(&sa, 0, sizeof(sa));
ss.ss_size = sizeof(g_alt_stack);
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 2659b0e213..49a38ce544 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -62,7 +62,6 @@ using std::chrono::system_clock;
namespace grpc {
namespace testing {
-
namespace {
const char* kServerCancelAfterReads = "cancel_after_reads";
@@ -195,8 +194,6 @@ const char TestAuthMetadataProcessor::kGoodGuy[] = "Dr Jekyll";
const char TestAuthMetadataProcessor::kIdentityPropName[] = "novel identity";
-} // namespace
-
class Proxy : public ::grpc::cpp::test::util::TestService::Service {
public:
Proxy(std::shared_ptr<Channel> channel)
@@ -353,14 +350,24 @@ class TestServiceImplDupPkg
}
};
-/* Param is whether or not to use a proxy -- some tests use TEST_F as they don't
- need this functionality */
-class End2endTest : public ::testing::TestWithParam<bool> {
+class TestScenario {
+ public:
+ TestScenario(bool proxy, bool tls) : use_proxy(proxy), use_tls(tls) {}
+ void Log() const {
+ gpr_log(GPR_INFO, "Scenario: proxy %d, tls %d", use_proxy, use_tls);
+ }
+ bool use_proxy;
+ bool use_tls;
+};
+
+class End2endTest : public ::testing::TestWithParam<TestScenario> {
protected:
End2endTest()
: is_server_started_(false),
kMaxMessageSize_(8192),
- special_service_("special") {}
+ special_service_("special") {
+ GetParam().Log();
+ }
void TearDown() GRPC_OVERRIDE {
if (is_server_started_) {
@@ -374,13 +381,16 @@ class End2endTest : public ::testing::TestWithParam<bool> {
server_address_ << "127.0.0.1:" << port;
// Setup server
ServerBuilder builder;
- SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
- test_server1_cert};
- SslServerCredentialsOptions ssl_opts;
- ssl_opts.pem_root_certs = "";
- ssl_opts.pem_key_cert_pairs.push_back(pkcp);
- auto server_creds = SslServerCredentials(ssl_opts);
- server_creds->SetAuthMetadataProcessor(processor);
+ auto server_creds = InsecureServerCredentials();
+ if (GetParam().use_tls) {
+ SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
+ test_server1_cert};
+ SslServerCredentialsOptions ssl_opts;
+ ssl_opts.pem_root_certs = "";
+ ssl_opts.pem_key_cert_pairs.push_back(pkcp);
+ server_creds = SslServerCredentials(ssl_opts);
+ server_creds->SetAuthMetadataProcessor(processor);
+ }
builder.AddListeningPort(server_address_.str(), server_creds);
builder.RegisterService(&service_);
builder.RegisterService("foo.test.youtube.com", &special_service_);
@@ -396,17 +406,20 @@ class End2endTest : public ::testing::TestWithParam<bool> {
StartServer(std::shared_ptr<AuthMetadataProcessor>());
}
EXPECT_TRUE(is_server_started_);
- SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
ChannelArguments args;
- args.SetSslTargetNameOverride("foo.test.google.fr");
+ auto channel_creds = InsecureCredentials();
+ if (GetParam().use_tls) {
+ SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
+ args.SetSslTargetNameOverride("foo.test.google.fr");
+ channel_creds = SslCredentials(ssl_opts);
+ }
args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test");
- channel_ = CreateCustomChannel(server_address_.str(),
- SslCredentials(ssl_opts), args);
+ channel_ = CreateCustomChannel(server_address_.str(), channel_creds, args);
}
- void ResetStub(bool use_proxy) {
+ void ResetStub() {
ResetChannel();
- if (use_proxy) {
+ if (GetParam().use_proxy) {
proxy_service_.reset(new Proxy(channel_));
int port = grpc_pick_unused_port_or_die();
std::ostringstream proxyaddr;
@@ -450,124 +463,8 @@ static void SendRpc(grpc::cpp::test::util::TestService::Stub* stub,
}
}
-TEST_F(End2endTest, SimpleRpcWithHost) {
- ResetStub(false);
-
- EchoRequest request;
- EchoResponse response;
- request.set_message("Hello");
-
- ClientContext context;
- context.set_authority("foo.test.youtube.com");
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_EQ(response.message(), request.message());
- EXPECT_TRUE(response.has_param());
- EXPECT_EQ("special", response.param().host());
- EXPECT_TRUE(s.ok());
-}
-
-TEST_P(End2endTest, SimpleRpc) {
- ResetStub(GetParam());
- SendRpc(stub_.get(), 1);
-}
-
-TEST_P(End2endTest, MultipleRpcs) {
- ResetStub(GetParam());
- std::vector<std::thread*> threads;
- for (int i = 0; i < 10; ++i) {
- threads.push_back(new std::thread(SendRpc, stub_.get(), 10));
- }
- for (int i = 0; i < 10; ++i) {
- threads[i]->join();
- delete threads[i];
- }
-}
-
-// Set a 10us deadline and make sure proper error is returned.
-TEST_P(End2endTest, RpcDeadlineExpires) {
- ResetStub(GetParam());
- EchoRequest request;
- EchoResponse response;
- request.set_message("Hello");
-
- ClientContext context;
- std::chrono::system_clock::time_point deadline =
- std::chrono::system_clock::now() + std::chrono::microseconds(10);
- context.set_deadline(deadline);
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, s.error_code());
-}
-
-// Set a long but finite deadline.
-TEST_P(End2endTest, RpcLongDeadline) {
- ResetStub(GetParam());
- EchoRequest request;
- EchoResponse response;
- request.set_message("Hello");
-
- ClientContext context;
- std::chrono::system_clock::time_point deadline =
- std::chrono::system_clock::now() + std::chrono::hours(1);
- context.set_deadline(deadline);
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_EQ(response.message(), request.message());
- EXPECT_TRUE(s.ok());
-}
-
-// Ask server to echo back the deadline it sees.
-TEST_P(End2endTest, EchoDeadline) {
- ResetStub(GetParam());
- EchoRequest request;
- EchoResponse response;
- request.set_message("Hello");
- request.mutable_param()->set_echo_deadline(true);
-
- ClientContext context;
- std::chrono::system_clock::time_point deadline =
- std::chrono::system_clock::now() + std::chrono::seconds(100);
- context.set_deadline(deadline);
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_EQ(response.message(), request.message());
- EXPECT_TRUE(s.ok());
- gpr_timespec sent_deadline;
- Timepoint2Timespec(deadline, &sent_deadline);
- // Allow 1 second error.
- EXPECT_LE(response.param().request_deadline() - sent_deadline.tv_sec, 1);
- EXPECT_GE(response.param().request_deadline() - sent_deadline.tv_sec, -1);
-}
-
-// Ask server to echo back the deadline it sees. The rpc has no deadline.
-TEST_P(End2endTest, EchoDeadlineForNoDeadlineRpc) {
- ResetStub(GetParam());
- EchoRequest request;
- EchoResponse response;
- request.set_message("Hello");
- request.mutable_param()->set_echo_deadline(true);
-
- ClientContext context;
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_EQ(response.message(), request.message());
- EXPECT_TRUE(s.ok());
- EXPECT_EQ(response.param().request_deadline(),
- gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec);
-}
-
-TEST_P(End2endTest, UnimplementedRpc) {
- ResetStub(GetParam());
- EchoRequest request;
- EchoResponse response;
- request.set_message("Hello");
-
- ClientContext context;
- Status s = stub_->Unimplemented(&context, request, &response);
- EXPECT_FALSE(s.ok());
- EXPECT_EQ(s.error_code(), grpc::StatusCode::UNIMPLEMENTED);
- EXPECT_EQ(s.error_message(), "");
- EXPECT_EQ(response.message(), "");
-}
-
-TEST_F(End2endTest, RequestStreamOneRequest) {
- ResetStub(false);
+TEST_P(End2endTest, RequestStreamOneRequest) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -581,8 +478,8 @@ TEST_F(End2endTest, RequestStreamOneRequest) {
EXPECT_TRUE(s.ok());
}
-TEST_F(End2endTest, RequestStreamTwoRequests) {
- ResetStub(false);
+TEST_P(End2endTest, RequestStreamTwoRequests) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -597,8 +494,8 @@ TEST_F(End2endTest, RequestStreamTwoRequests) {
EXPECT_TRUE(s.ok());
}
-TEST_F(End2endTest, ResponseStream) {
- ResetStub(false);
+TEST_P(End2endTest, ResponseStream) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -617,8 +514,8 @@ TEST_F(End2endTest, ResponseStream) {
EXPECT_TRUE(s.ok());
}
-TEST_F(End2endTest, BidiStream) {
- ResetStub(false);
+TEST_P(End2endTest, BidiStream) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -650,8 +547,8 @@ TEST_F(End2endTest, BidiStream) {
// Talk to the two services with the same name but different package names.
// The two stubs are created on the same channel.
-TEST_F(End2endTest, DiffPackageServices) {
- ResetStub(false);
+TEST_P(End2endTest, DiffPackageServices) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
request.set_message("Hello");
@@ -670,33 +567,6 @@ TEST_F(End2endTest, DiffPackageServices) {
EXPECT_TRUE(s.ok());
}
-// rpc and stream should fail on bad credentials.
-TEST_F(End2endTest, BadCredentials) {
- std::shared_ptr<Credentials> bad_creds = GoogleRefreshTokenCredentials("");
- EXPECT_EQ(static_cast<Credentials*>(nullptr), bad_creds.get());
- std::shared_ptr<Channel> channel =
- CreateChannel(server_address_.str(), bad_creds);
- std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub(
- grpc::cpp::test::util::TestService::NewStub(channel));
- EchoRequest request;
- EchoResponse response;
- ClientContext context;
- request.set_message("Hello");
-
- Status s = stub->Echo(&context, request, &response);
- EXPECT_EQ("", response.message());
- EXPECT_FALSE(s.ok());
- EXPECT_EQ(StatusCode::INVALID_ARGUMENT, s.error_code());
- EXPECT_EQ("Invalid credentials.", s.error_message());
-
- ClientContext context2;
- auto stream = stub->BidiStream(&context2);
- s = stream->Finish();
- EXPECT_FALSE(s.ok());
- EXPECT_EQ(StatusCode::INVALID_ARGUMENT, s.error_code());
- EXPECT_EQ("Invalid credentials.", s.error_message());
-}
-
void CancelRpc(ClientContext* context, int delay_us, TestServiceImpl* service) {
gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_micros(delay_us, GPR_TIMESPAN)));
@@ -705,40 +575,9 @@ void CancelRpc(ClientContext* context, int delay_us, TestServiceImpl* service) {
context->TryCancel();
}
-// Client cancels rpc after 10ms
-TEST_P(End2endTest, ClientCancelsRpc) {
- ResetStub(GetParam());
- EchoRequest request;
- EchoResponse response;
- request.set_message("Hello");
- const int kCancelDelayUs = 10 * 1000;
- request.mutable_param()->set_client_cancel_after_us(kCancelDelayUs);
-
- ClientContext context;
- std::thread cancel_thread(CancelRpc, &context, kCancelDelayUs, &service_);
- Status s = stub_->Echo(&context, request, &response);
- cancel_thread.join();
- EXPECT_EQ(StatusCode::CANCELLED, s.error_code());
- EXPECT_EQ(s.error_message(), "Cancelled");
-}
-
-// Server cancels rpc after 1ms
-TEST_P(End2endTest, ServerCancelsRpc) {
- ResetStub(GetParam());
- EchoRequest request;
- EchoResponse response;
- request.set_message("Hello");
- request.mutable_param()->set_server_cancel_after_us(1000);
-
- ClientContext context;
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_EQ(StatusCode::CANCELLED, s.error_code());
- EXPECT_TRUE(s.error_message().empty());
-}
-
// Client cancels request stream after sending two messages
-TEST_F(End2endTest, ClientCancelsRequestStream) {
- ResetStub(false);
+TEST_P(End2endTest, ClientCancelsRequestStream) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -757,8 +596,8 @@ TEST_F(End2endTest, ClientCancelsRequestStream) {
}
// Client cancels server stream after sending some messages
-TEST_F(End2endTest, ClientCancelsResponseStream) {
- ResetStub(false);
+TEST_P(End2endTest, ClientCancelsResponseStream) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -789,8 +628,8 @@ TEST_F(End2endTest, ClientCancelsResponseStream) {
}
// Client cancels bidi stream after sending some messages
-TEST_F(End2endTest, ClientCancelsBidi) {
- ResetStub(false);
+TEST_P(End2endTest, ClientCancelsBidi) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -821,8 +660,8 @@ TEST_F(End2endTest, ClientCancelsBidi) {
EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code());
}
-TEST_F(End2endTest, RpcMaxMessageSize) {
- ResetStub(false);
+TEST_P(End2endTest, RpcMaxMessageSize) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
request.set_message(string(kMaxMessageSize_ * 2, 'a'));
@@ -832,6 +671,328 @@ TEST_F(End2endTest, RpcMaxMessageSize) {
EXPECT_FALSE(s.ok());
}
+// Client sends 20 requests and the server returns CANCELLED status after
+// reading 10 requests.
+TEST_P(End2endTest, RequestStreamServerEarlyCancelTest) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ ClientContext context;
+
+ context.AddMetadata(kServerCancelAfterReads, "10");
+ auto stream = stub_->RequestStream(&context, &response);
+ request.set_message("hello");
+ int send_messages = 20;
+ while (send_messages > 0) {
+ EXPECT_TRUE(stream->Write(request));
+ send_messages--;
+ }
+ stream->WritesDone();
+ Status s = stream->Finish();
+ EXPECT_EQ(s.error_code(), StatusCode::CANCELLED);
+}
+
+void ReaderThreadFunc(ClientReaderWriter<EchoRequest, EchoResponse>* stream,
+ gpr_event* ev) {
+ EchoResponse resp;
+ gpr_event_set(ev, (void*)1);
+ while (stream->Read(&resp)) {
+ gpr_log(GPR_INFO, "Read message");
+ }
+}
+
+// Run a Read and a WritesDone simultaneously.
+TEST_P(End2endTest, SimultaneousReadWritesDone) {
+ ResetStub();
+ ClientContext context;
+ gpr_event ev;
+ gpr_event_init(&ev);
+ auto stream = stub_->BidiStream(&context);
+ std::thread reader_thread(ReaderThreadFunc, stream.get(), &ev);
+ gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
+ stream->WritesDone();
+ Status s = stream->Finish();
+ EXPECT_TRUE(s.ok());
+ reader_thread.join();
+}
+
+TEST_P(End2endTest, ChannelState) {
+ ResetStub();
+ // Start IDLE
+ EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false));
+
+ // Did not ask to connect, no state change.
+ CompletionQueue cq;
+ std::chrono::system_clock::time_point deadline =
+ std::chrono::system_clock::now() + std::chrono::milliseconds(10);
+ channel_->NotifyOnStateChange(GRPC_CHANNEL_IDLE, deadline, &cq, NULL);
+ void* tag;
+ bool ok = true;
+ cq.Next(&tag, &ok);
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(true));
+ EXPECT_TRUE(channel_->WaitForStateChange(GRPC_CHANNEL_IDLE,
+ gpr_inf_future(GPR_CLOCK_REALTIME)));
+ EXPECT_EQ(GRPC_CHANNEL_CONNECTING, channel_->GetState(false));
+}
+
+// Takes 10s.
+TEST_P(End2endTest, ChannelStateTimeout) {
+ if (GetParam().use_tls) {
+ return;
+ }
+ int port = grpc_pick_unused_port_or_die();
+ std::ostringstream server_address;
+ server_address << "127.0.0.1:" << port;
+ // Channel to non-existing server
+ auto channel = CreateChannel(server_address.str(), InsecureCredentials());
+ // Start IDLE
+ EXPECT_EQ(GRPC_CHANNEL_IDLE, channel->GetState(true));
+
+ auto state = GRPC_CHANNEL_IDLE;
+ for (int i = 0; i < 10; i++) {
+ channel->WaitForStateChange(
+ state, std::chrono::system_clock::now() + std::chrono::seconds(1));
+ state = channel->GetState(false);
+ }
+}
+
+// Talking to a non-existing service.
+TEST_P(End2endTest, NonExistingService) {
+ ResetChannel();
+ std::unique_ptr<grpc::cpp::test::util::UnimplementedService::Stub> stub;
+ stub = grpc::cpp::test::util::UnimplementedService::NewStub(channel_);
+
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+
+ ClientContext context;
+ Status s = stub->Unimplemented(&context, request, &response);
+ EXPECT_EQ(StatusCode::UNIMPLEMENTED, s.error_code());
+ EXPECT_EQ("", s.error_message());
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Test with and without a proxy.
+class ProxyEnd2endTest : public End2endTest {
+ protected:
+};
+
+TEST_P(ProxyEnd2endTest, SimpleRpc) {
+ ResetStub();
+ SendRpc(stub_.get(), 1);
+}
+
+TEST_P(ProxyEnd2endTest, MultipleRpcs) {
+ ResetStub();
+ std::vector<std::thread*> threads;
+ for (int i = 0; i < 10; ++i) {
+ threads.push_back(new std::thread(SendRpc, stub_.get(), 10));
+ }
+ for (int i = 0; i < 10; ++i) {
+ threads[i]->join();
+ delete threads[i];
+ }
+}
+
+// Set a 10us deadline and make sure proper error is returned.
+TEST_P(ProxyEnd2endTest, RpcDeadlineExpires) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+
+ ClientContext context;
+ std::chrono::system_clock::time_point deadline =
+ std::chrono::system_clock::now() + std::chrono::microseconds(10);
+ context.set_deadline(deadline);
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, s.error_code());
+}
+
+// Set a long but finite deadline.
+TEST_P(ProxyEnd2endTest, RpcLongDeadline) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+
+ ClientContext context;
+ std::chrono::system_clock::time_point deadline =
+ std::chrono::system_clock::now() + std::chrono::hours(1);
+ context.set_deadline(deadline);
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(response.message(), request.message());
+ EXPECT_TRUE(s.ok());
+}
+
+// Ask server to echo back the deadline it sees.
+TEST_P(ProxyEnd2endTest, EchoDeadline) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+ request.mutable_param()->set_echo_deadline(true);
+
+ ClientContext context;
+ std::chrono::system_clock::time_point deadline =
+ std::chrono::system_clock::now() + std::chrono::seconds(100);
+ context.set_deadline(deadline);
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(response.message(), request.message());
+ EXPECT_TRUE(s.ok());
+ gpr_timespec sent_deadline;
+ Timepoint2Timespec(deadline, &sent_deadline);
+ // Allow 1 second error.
+ EXPECT_LE(response.param().request_deadline() - sent_deadline.tv_sec, 1);
+ EXPECT_GE(response.param().request_deadline() - sent_deadline.tv_sec, -1);
+}
+
+// Ask server to echo back the deadline it sees. The rpc has no deadline.
+TEST_P(ProxyEnd2endTest, EchoDeadlineForNoDeadlineRpc) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+ request.mutable_param()->set_echo_deadline(true);
+
+ ClientContext context;
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(response.message(), request.message());
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(response.param().request_deadline(),
+ gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec);
+}
+
+TEST_P(ProxyEnd2endTest, UnimplementedRpc) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+
+ ClientContext context;
+ Status s = stub_->Unimplemented(&context, request, &response);
+ EXPECT_FALSE(s.ok());
+ EXPECT_EQ(s.error_code(), grpc::StatusCode::UNIMPLEMENTED);
+ EXPECT_EQ(s.error_message(), "");
+ EXPECT_EQ(response.message(), "");
+}
+
+// Client cancels rpc after 10ms
+TEST_P(ProxyEnd2endTest, ClientCancelsRpc) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+ const int kCancelDelayUs = 10 * 1000;
+ request.mutable_param()->set_client_cancel_after_us(kCancelDelayUs);
+
+ ClientContext context;
+ std::thread cancel_thread(CancelRpc, &context, kCancelDelayUs, &service_);
+ Status s = stub_->Echo(&context, request, &response);
+ cancel_thread.join();
+ EXPECT_EQ(StatusCode::CANCELLED, s.error_code());
+ EXPECT_EQ(s.error_message(), "Cancelled");
+}
+
+// Server cancels rpc after 1ms
+TEST_P(ProxyEnd2endTest, ServerCancelsRpc) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+ request.mutable_param()->set_server_cancel_after_us(1000);
+
+ ClientContext context;
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(StatusCode::CANCELLED, s.error_code());
+ EXPECT_TRUE(s.error_message().empty());
+}
+
+// Make the response larger than the flow control window.
+TEST_P(ProxyEnd2endTest, HugeResponse) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("huge response");
+ const size_t kResponseSize = 1024 * (1024 + 10);
+ request.mutable_param()->set_response_message_length(kResponseSize);
+
+ ClientContext context;
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(kResponseSize, response.message().size());
+ EXPECT_TRUE(s.ok());
+}
+
+TEST_P(ProxyEnd2endTest, Peer) {
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("hello");
+ request.mutable_param()->set_echo_peer(true);
+
+ ClientContext context;
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(response.message(), request.message());
+ EXPECT_TRUE(s.ok());
+ EXPECT_TRUE(CheckIsLocalhost(response.param().peer()));
+ EXPECT_TRUE(CheckIsLocalhost(context.peer()));
+}
+
+//////////////////////////////////////////////////////////////////////////
+class SecureEnd2endTest : public End2endTest {
+ protected:
+ SecureEnd2endTest() {
+ GPR_ASSERT(!GetParam().use_proxy);
+ GPR_ASSERT(GetParam().use_tls);
+ }
+};
+
+TEST_P(SecureEnd2endTest, SimpleRpcWithHost) {
+ ResetStub();
+
+ EchoRequest request;
+ EchoResponse response;
+ request.set_message("Hello");
+
+ ClientContext context;
+ context.set_authority("foo.test.youtube.com");
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(response.message(), request.message());
+ EXPECT_TRUE(response.has_param());
+ EXPECT_EQ("special", response.param().host());
+ EXPECT_TRUE(s.ok());
+}
+
+// rpc and stream should fail on bad credentials.
+TEST_P(SecureEnd2endTest, BadCredentials) {
+ std::shared_ptr<Credentials> bad_creds = GoogleRefreshTokenCredentials("");
+ EXPECT_EQ(static_cast<Credentials*>(nullptr), bad_creds.get());
+ std::shared_ptr<Channel> channel =
+ CreateChannel(server_address_.str(), bad_creds);
+ std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub(
+ grpc::cpp::test::util::TestService::NewStub(channel));
+ EchoRequest request;
+ EchoResponse response;
+ ClientContext context;
+ request.set_message("Hello");
+
+ Status s = stub->Echo(&context, request, &response);
+ EXPECT_EQ("", response.message());
+ EXPECT_FALSE(s.ok());
+ EXPECT_EQ(StatusCode::INVALID_ARGUMENT, s.error_code());
+ EXPECT_EQ("Invalid credentials.", s.error_message());
+
+ ClientContext context2;
+ auto stream = stub->BidiStream(&context2);
+ s = stream->Finish();
+ EXPECT_FALSE(s.ok());
+ EXPECT_EQ(StatusCode::INVALID_ARGUMENT, s.error_code());
+ EXPECT_EQ("Invalid credentials.", s.error_message());
+}
+
bool MetadataContains(
const std::multimap<grpc::string_ref, grpc::string_ref>& metadata,
const grpc::string& key, const grpc::string& value) {
@@ -847,8 +1008,45 @@ bool MetadataContains(
return count == 1;
}
-TEST_F(End2endTest, SetPerCallCredentials) {
- ResetStub(false);
+TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorSuccess) {
+ auto* processor = new TestAuthMetadataProcessor(true);
+ StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ ClientContext context;
+ context.set_credentials(processor->GetCompatibleClientCreds());
+ request.set_message("Hello");
+ request.mutable_param()->set_echo_metadata(true);
+ request.mutable_param()->set_expected_client_identity(
+ TestAuthMetadataProcessor::kGoodGuy);
+
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_EQ(request.message(), response.message());
+ EXPECT_TRUE(s.ok());
+
+ // Metadata should have been consumed by the processor.
+ EXPECT_FALSE(MetadataContains(
+ context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY,
+ grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy));
+}
+
+TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorFailure) {
+ auto* processor = new TestAuthMetadataProcessor(true);
+ StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+ ResetStub();
+ EchoRequest request;
+ EchoResponse response;
+ ClientContext context;
+ context.set_credentials(processor->GetIncompatibleClientCreds());
+ request.set_message("Hello");
+
+ Status s = stub_->Echo(&context, request, &response);
+ EXPECT_FALSE(s.ok());
+ EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
+}
+TEST_P(SecureEnd2endTest, SetPerCallCredentials) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -869,8 +1067,8 @@ TEST_F(End2endTest, SetPerCallCredentials) {
"fake_selector"));
}
-TEST_F(End2endTest, InsecurePerCallCredentials) {
- ResetStub(false);
+TEST_P(SecureEnd2endTest, InsecurePerCallCredentials) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -884,8 +1082,8 @@ TEST_F(End2endTest, InsecurePerCallCredentials) {
EXPECT_EQ("Failed to set credentials to rpc.", s.error_message());
}
-TEST_F(End2endTest, OverridePerCallCredentials) {
- ResetStub(false);
+TEST_P(SecureEnd2endTest, OverridePerCallCredentials) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -915,8 +1113,8 @@ TEST_F(End2endTest, OverridePerCallCredentials) {
EXPECT_TRUE(s.ok());
}
-TEST_F(End2endTest, NonBlockingAuthMetadataPluginFailure) {
- ResetStub(false);
+TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -932,10 +1130,10 @@ TEST_F(End2endTest, NonBlockingAuthMetadataPluginFailure) {
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
-TEST_F(End2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) {
+TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) {
auto* processor = new TestAuthMetadataProcessor(false);
StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
- ResetStub(false);
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -955,10 +1153,10 @@ TEST_F(End2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) {
grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy));
}
-TEST_F(End2endTest, NonBlockingAuthMetadataPluginAndProcessorFailure) {
+TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorFailure) {
auto* processor = new TestAuthMetadataProcessor(false);
StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
- ResetStub(false);
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -970,8 +1168,8 @@ TEST_F(End2endTest, NonBlockingAuthMetadataPluginAndProcessorFailure) {
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
-TEST_F(End2endTest, BlockingAuthMetadataPluginFailure) {
- ResetStub(false);
+TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
@@ -987,67 +1185,8 @@ TEST_F(End2endTest, BlockingAuthMetadataPluginFailure) {
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
-TEST_F(End2endTest, BlockingAuthMetadataPluginAndProcessorSuccess) {
- auto* processor = new TestAuthMetadataProcessor(true);
- StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
- ResetStub(false);
- EchoRequest request;
- EchoResponse response;
- ClientContext context;
- context.set_credentials(processor->GetCompatibleClientCreds());
- request.set_message("Hello");
- request.mutable_param()->set_echo_metadata(true);
- request.mutable_param()->set_expected_client_identity(
- TestAuthMetadataProcessor::kGoodGuy);
-
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_EQ(request.message(), response.message());
- EXPECT_TRUE(s.ok());
-
- // Metadata should have been consumed by the processor.
- EXPECT_FALSE(MetadataContains(
- context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY,
- grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy));
-}
-
-TEST_F(End2endTest, BlockingAuthMetadataPluginAndProcessorFailure) {
- auto* processor = new TestAuthMetadataProcessor(true);
- StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
- ResetStub(false);
- EchoRequest request;
- EchoResponse response;
- ClientContext context;
- context.set_credentials(processor->GetIncompatibleClientCreds());
- request.set_message("Hello");
-
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_FALSE(s.ok());
- EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
-}
-
-// Client sends 20 requests and the server returns CANCELLED status after
-// reading 10 requests.
-TEST_F(End2endTest, RequestStreamServerEarlyCancelTest) {
- ResetStub(false);
- EchoRequest request;
- EchoResponse response;
- ClientContext context;
-
- context.AddMetadata(kServerCancelAfterReads, "10");
- auto stream = stub_->RequestStream(&context, &response);
- request.set_message("hello");
- int send_messages = 20;
- while (send_messages > 0) {
- EXPECT_TRUE(stream->Write(request));
- send_messages--;
- }
- stream->WritesDone();
- Status s = stream->Finish();
- EXPECT_EQ(s.error_code(), StatusCode::CANCELLED);
-}
-
-TEST_F(End2endTest, ClientAuthContext) {
- ResetStub(false);
+TEST_P(SecureEnd2endTest, ClientAuthContext) {
+ ResetStub();
EchoRequest request;
EchoResponse response;
request.set_message("Hello");
@@ -1072,119 +1211,20 @@ TEST_F(End2endTest, ClientAuthContext) {
EXPECT_EQ("*.test.youtube.com", ToString(auth_ctx->GetPeerIdentity()[2]));
}
-// Make the response larger than the flow control window.
-TEST_P(End2endTest, HugeResponse) {
- ResetStub(GetParam());
- EchoRequest request;
- EchoResponse response;
- request.set_message("huge response");
- const size_t kResponseSize = 1024 * (1024 + 10);
- request.mutable_param()->set_response_message_length(kResponseSize);
+INSTANTIATE_TEST_CASE_P(End2end, End2endTest,
+ ::testing::Values(TestScenario(false, true),
+ TestScenario(false, false)));
- ClientContext context;
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_EQ(kResponseSize, response.message().size());
- EXPECT_TRUE(s.ok());
-}
+INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest,
+ ::testing::Values(TestScenario(true, true),
+ TestScenario(true, false),
+ TestScenario(false, true),
+ TestScenario(false, false)));
-namespace {
-void ReaderThreadFunc(ClientReaderWriter<EchoRequest, EchoResponse>* stream,
- gpr_event* ev) {
- EchoResponse resp;
- gpr_event_set(ev, (void*)1);
- while (stream->Read(&resp)) {
- gpr_log(GPR_INFO, "Read message");
- }
-}
-} // namespace
-
-// Run a Read and a WritesDone simultaneously.
-TEST_F(End2endTest, SimultaneousReadWritesDone) {
- ResetStub(false);
- ClientContext context;
- gpr_event ev;
- gpr_event_init(&ev);
- auto stream = stub_->BidiStream(&context);
- std::thread reader_thread(ReaderThreadFunc, stream.get(), &ev);
- gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
- stream->WritesDone();
- Status s = stream->Finish();
- EXPECT_TRUE(s.ok());
- reader_thread.join();
-}
-
-TEST_P(End2endTest, Peer) {
- ResetStub(GetParam());
- EchoRequest request;
- EchoResponse response;
- request.set_message("hello");
- request.mutable_param()->set_echo_peer(true);
-
- ClientContext context;
- Status s = stub_->Echo(&context, request, &response);
- EXPECT_EQ(response.message(), request.message());
- EXPECT_TRUE(s.ok());
- EXPECT_TRUE(CheckIsLocalhost(response.param().peer()));
- EXPECT_TRUE(CheckIsLocalhost(context.peer()));
-}
-
-TEST_F(End2endTest, ChannelState) {
- ResetStub(false);
- // Start IDLE
- EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(false));
-
- // Did not ask to connect, no state change.
- CompletionQueue cq;
- std::chrono::system_clock::time_point deadline =
- std::chrono::system_clock::now() + std::chrono::milliseconds(10);
- channel_->NotifyOnStateChange(GRPC_CHANNEL_IDLE, deadline, &cq, NULL);
- void* tag;
- bool ok = true;
- cq.Next(&tag, &ok);
- EXPECT_FALSE(ok);
-
- EXPECT_EQ(GRPC_CHANNEL_IDLE, channel_->GetState(true));
- EXPECT_TRUE(channel_->WaitForStateChange(GRPC_CHANNEL_IDLE,
- gpr_inf_future(GPR_CLOCK_REALTIME)));
- EXPECT_EQ(GRPC_CHANNEL_CONNECTING, channel_->GetState(false));
-}
-
-// Takes 10s.
-TEST_F(End2endTest, ChannelStateTimeout) {
- int port = grpc_pick_unused_port_or_die();
- std::ostringstream server_address;
- server_address << "127.0.0.1:" << port;
- // Channel to non-existing server
- auto channel = CreateChannel(server_address.str(), InsecureCredentials());
- // Start IDLE
- EXPECT_EQ(GRPC_CHANNEL_IDLE, channel->GetState(true));
-
- auto state = GRPC_CHANNEL_IDLE;
- for (int i = 0; i < 10; i++) {
- channel->WaitForStateChange(
- state, std::chrono::system_clock::now() + std::chrono::seconds(1));
- state = channel->GetState(false);
- }
-}
-
-// Talking to a non-existing service.
-TEST_F(End2endTest, NonExistingService) {
- ResetChannel();
- std::unique_ptr<grpc::cpp::test::util::UnimplementedService::Stub> stub;
- stub = grpc::cpp::test::util::UnimplementedService::NewStub(channel_);
-
- EchoRequest request;
- EchoResponse response;
- request.set_message("Hello");
-
- ClientContext context;
- Status s = stub->Unimplemented(&context, request, &response);
- EXPECT_EQ(StatusCode::UNIMPLEMENTED, s.error_code());
- EXPECT_EQ("", s.error_message());
-}
-
-INSTANTIATE_TEST_CASE_P(End2end, End2endTest, ::testing::Values(false, true));
+INSTANTIATE_TEST_CASE_P(SecureEnd2end, SecureEnd2endTest,
+ ::testing::Values(TestScenario(false, true)));
+} // namespace
} // namespace testing
} // namespace grpc
diff --git a/vsprojects/coapp/zlib/README.md b/vsprojects/coapp/zlib/README.md
new file mode 100644
index 0000000000..c81a57a48b
--- /dev/null
+++ b/vsprojects/coapp/zlib/README.md
@@ -0,0 +1,35 @@
+Zlib Native Nuget package
+-------------------------
+
+Uses [CoApp](http://coapp.org/) project to build the zlib package.
+
+Prerequisites
+-------------
+Multiple versions of VS installed to be able to build all the targets:
+* Visual Studio 2013
+* Visual Studio 2010 (you might need SP1 to prevent LNK1123 error)
+
+CoApp toolkit: http://downloads.coapp.org/files/CoApp.Tools.Powershell.msi
+
+More details on installation: http://coapp.org/tutorials/installation.html
+
+Building
+--------
+
+Build all flavors of zlib library using the provided batch file.
+```
+buildall.bat
+```
+
+Then, create NuGet package using powershell (you'll need the CoApp toolkit installed):
+```
+[THIS_DIRECTORY]> Write-NuGetPackage grpc.dependencies.zlib.autopkg
+```
+
+This will create three NuGet packages:
+* the main dev package
+* the redistributable package that contains just the binaries and no headers
+* the symbols package (debug symbols)
+
+Later, you can push the package to NuGet.org repo.
+Attention: before pusing the resulting nuget package to public nuget repo, you have to be 100% sure it works correctly - there’s no way how to delete or update an already existing package. \ No newline at end of file
diff --git a/vsprojects/coapp/zlib/buildall.bat b/vsprojects/coapp/zlib/buildall.bat
new file mode 100644
index 0000000000..a71e56f4ae
--- /dev/null
+++ b/vsprojects/coapp/zlib/buildall.bat
@@ -0,0 +1,51 @@
+@echo off
+setlocal
+
+setlocal
+call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64
+call :build x64 Release v120 || goto :eof
+call :build x64 Debug v120 || goto :eof
+endlocal
+
+setlocal
+call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86
+call :build Win32 Release v120 || goto :eof
+call :build Win32 Debug v120 || goto :eof
+endlocal
+
+REM setlocal
+REM call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" amd64
+REM call :build x64 Release v110 || goto :eof
+REM call :build x64 Debug v110 || goto :eof
+REM endlocal
+
+REM setlocal
+REM call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x86
+REM call :build Win32 Release v110 || goto :eof
+REM call :build Win32 Debug v110 || goto :eof
+REM endlocal
+
+REM setlocal
+REM call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" amd64
+REM call :build x64 Release v100 || goto :eof
+REM call :build x64 Debug v100 || goto :eof
+REM endlocal
+
+setlocal
+call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
+call :build Win32 Release v100 || goto :eof
+call :build Win32 Debug v100 || goto :eof
+endlocal
+
+goto :eof
+
+:build
+msbuild /P:Platform=%1 /P:Configuration=%2 /P:PlatformToolset=%3 /P:UsesConfigurationType=Dynamic /P:CallingConvention=cdecl .\zlib.sln || goto :eof
+msbuild /P:Platform=%1 /P:Configuration=%2 /P:PlatformToolset=%3 /P:UsesConfigurationType=Dynamic /P:CallingConvention=stdcall .\zlib.sln || goto :eof
+msbuild /P:Platform=%1 /P:Configuration=%2 /P:PlatformToolset=%3 /P:UsesConfigurationType=Static /P:CallingConvention=cdecl .\zlib.sln || goto :eof
+msbuild /P:Platform=%1 /P:Configuration=%2 /P:PlatformToolset=%3 /P:UsesConfigurationType=Static /P:CallingConvention=stdcall .\zlib.sln || goto :eof
+msbuild /P:Platform=%1 /P:Configuration=%2 /P:PlatformToolset=%3 /P:UsesConfigurationType=ltcg /P:CallingConvention=cdecl .\zlib.sln || goto :eof
+msbuild /P:Platform=%1 /P:Configuration=%2 /P:PlatformToolset=%3 /P:UsesConfigurationType=ltcg /P:CallingConvention=stdcall .\zlib.sln || goto :eof
+goto :eof
+
+
diff --git a/vsprojects/coapp/zlib/grpc.dependencies.zlib.autopkg b/vsprojects/coapp/zlib/grpc.dependencies.zlib.autopkg
new file mode 100644
index 0000000000..01390b9434
--- /dev/null
+++ b/vsprojects/coapp/zlib/grpc.dependencies.zlib.autopkg
@@ -0,0 +1,102 @@
+@import @"version.inc";
+
+configurations {
+};
+
+#define {
+ package-id = "grpc.dependencies.zlib";
+}
+
+nuget {
+ // the nuspec file metadata. Gets created/updated on build
+ nuspec {
+ id = ${package-id};
+ version : ${package-version};
+ title: gRPC Native Dependency: ZLib compression library;
+ authors: {Jean-loup Gailly, Mark Adler, Garrett Serack, Tim Rogers};
+ owners: {Jan Tattermusch};
+ licenseUrl: "http://zlib.net/zlib-license.html";
+ projectUrl: "http://github.com/jtattermusch/zlib";
+ iconUrl: "http://zlib.net/images/zlib3d-b1.png";
+ requireLicenseAcceptance:false;
+ summary:A zlib library;
+ description: @"A native zlib library.
+ zlib homepage: http://zlib.net";
+ releaseNotes: "Release of zlib 1.2.8 libraries.";
+ copyright: Copyright 2013;
+ tags: { zlib, native, CoApp };
+
+ };
+
+ // the files that go into the content folders
+ // (inserted into the nuspec file)
+ files {
+ // .targets file that are applied when redist package is installed from a managed project.
+ managed_build: {
+ #output {
+ package = redist;
+ };
+ #destination = "\build\portable-net45";
+ "managed_targets\${package-id}.redist.props";
+ "managed_targets\${package-id}.redist.targets";
+ };
+
+ include: { ..\..\..\third_party\zlib\zlib.h, ..\..\..\third_party\zlib\zconf.h };
+
+ docs: { ..\..\..\third_party\zlib\doc\**\* };
+
+ source += {
+ "..\..\..\third_party\zlib\adler32.c",
+ "..\..\..\third_party\zlib\compress.c",
+ "..\..\..\third_party\zlib\crc32.c",
+ "..\..\..\third_party\zlib\deflate.c",
+ "..\..\..\third_party\zlib\gzclose.c",
+ "..\..\..\third_party\zlib\gzlib.c",
+ "..\..\..\third_party\zlib\gzread.c",
+ "..\..\..\third_party\zlib\gzwrite.c",
+ "..\..\..\third_party\zlib\infback.c",
+ "..\..\..\third_party\zlib\inffast.c",
+ "..\..\..\third_party\zlib\inflate.c",
+ "..\..\..\third_party\zlib\inftrees.c",
+ "..\..\..\third_party\zlib\trees.c",
+ "..\..\..\third_party\zlib\uncompr.c",
+ "..\..\..\third_party\zlib\zutil.c",
+ "..\..\..\third_party\zlib\crc32.h",
+ "..\..\..\third_party\zlib\deflate.h",
+ "..\..\..\third_party\zlib\gzguts.h",
+ "..\..\..\third_party\zlib\inffast.h",
+ "..\..\..\third_party\zlib\inffixed.h",
+ "..\..\..\third_party\zlib\inflate.h",
+ "..\..\..\third_party\zlib\inftrees.h",
+ "..\..\..\third_party\zlib\trees.h",
+ "..\..\..\third_party\zlib\zconf.h",
+ "..\..\..\third_party\zlib\zlib.h",
+ "..\..\..\third_party\zlib\zutil.h",
+ "..\..\..\third_party\zlib\contrib\masmx64\inffas8664.c",
+ };
+ ("v100,v120", "Win32,x64", "Release,Debug", "Dynamic", "cdecl,stdcall", "MultiByte") => {
+ [${0},${1},${2},${3},${4}] {
+ lib: { .\output\${0}\${1}\${2}\${3}\${4}\${5}\*.lib };
+ bin: { .\output\${0}\${1}\${2}\${3}\${4}\${5}\*.dll };
+ symbols: { .\output\${0}\${1}\${2}\${3}\${4}\${5}\*.pdb };
+ };
+ };
+ ("v100,v120", "Win32,x64", "Release,Debug", "Static,ltcg", "cdecl,stdcall", "MultiByte") => {
+ [${0},${1},${2},${3},${4}] {
+ lib: { .\output\${0}\${1}\${2}\${3}\${4}\${5}\*.lib };
+ };
+ };
+
+ };
+
+ // the VC++ .targets file that gets generated and inserted into the ${d_content} folder
+ targets {
+ Defines += HAS_ZLIB;
+ [dynamic]
+ Defines += ZLIB_DLL;
+ [stdcall]
+ Defines += ZLIB_WINAPI;
+
+ };
+}
+
diff --git a/vsprojects/coapp/zlib/managed_targets/grpc.dependencies.zlib.redist.props b/vsprojects/coapp/zlib/managed_targets/grpc.dependencies.zlib.redist.props
new file mode 100644
index 0000000000..bcb37de0f7
--- /dev/null
+++ b/vsprojects/coapp/zlib/managed_targets/grpc.dependencies.zlib.redist.props
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <!-- Whether or not copy native dependencies to output directory after building -->
+ <CopyNativeDependencies Condition=" '$(CopyNativeDependencies)' == '' ">true</CopyNativeDependencies>
+
+ <!-- Set defaults for native dependencies if not already set. Properties can be overriden in the project files. -->
+ <NativeDependenciesToolset Condition=" '$(NativeDependenciesToolset)' == '' ">v120</NativeDependenciesToolset>
+ <NativeDependenciesPlatform Condition=" '$(NativeDependenciesPlatform)' == '' ">Win32</NativeDependenciesPlatform>
+ <NativeDependenciesConfiguration Condition=" '$(NativeDependenciesConfiguration)' == '' ">Debug</NativeDependenciesConfiguration>
+ <ZlibCallingConvention Condition=" '$(ZlibCallingConvention)' == '' ">cdecl</ZlibCallingConvention>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/vsprojects/coapp/zlib/managed_targets/grpc.dependencies.zlib.redist.targets b/vsprojects/coapp/zlib/managed_targets/grpc.dependencies.zlib.redist.targets
new file mode 100644
index 0000000000..f00d97dc36
--- /dev/null
+++ b/vsprojects/coapp/zlib/managed_targets/grpc.dependencies.zlib.redist.targets
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Choose>
+ <!-- Under older versions of Monodevelop, Choose is not supported and is just ignored, which gives us the desired effect. -->
+ <When Condition=" '$(OS)' != 'Unix' ">
+ <ItemGroup Condition=" '$(CopyNativeDependencies)' == 'true' ">
+ <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\$(NativeDependenciesToolset)\$(NativeDependenciesPlatform)\$(NativeDependenciesConfiguration)\dynamic\$(ZlibCallingConvention)\zlib.dll">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ </ItemGroup>
+ </When>
+ <Otherwise />
+ </Choose>
+</Project> \ No newline at end of file
diff --git a/vsprojects/coapp/zlib/version.inc b/vsprojects/coapp/zlib/version.inc
new file mode 100644
index 0000000000..1f893a4951
--- /dev/null
+++ b/vsprojects/coapp/zlib/version.inc
@@ -0,0 +1 @@
+#define { package-version : 1.2.8.9; }
diff --git a/vsprojects/coapp/zlib/zlib.sln b/vsprojects/coapp/zlib/zlib.sln
new file mode 100644
index 0000000000..7c38e6e121
--- /dev/null
+++ b/vsprojects/coapp/zlib/zlib.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib.vcxproj", "{63BED288-E8C3-4345-B84D-2E64598DCF3A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {63BED288-E8C3-4345-B84D-2E64598DCF3A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {63BED288-E8C3-4345-B84D-2E64598DCF3A}.Debug|Win32.Build.0 = Debug|Win32
+ {63BED288-E8C3-4345-B84D-2E64598DCF3A}.Release|Win32.ActiveCfg = Release|Win32
+ {63BED288-E8C3-4345-B84D-2E64598DCF3A}.Release|Win32.Build.0 = Release|Win32
+ {63BED288-E8C3-4345-B84D-2E64598DCF3A}.Debug|x64.ActiveCfg = Debug|x64
+ {63BED288-E8C3-4345-B84D-2E64598DCF3A}.Debug|x64.Build.0 = Debug|x64
+ {63BED288-E8C3-4345-B84D-2E64598DCF3A}.Release|x64.ActiveCfg = Release|x64
+ {63BED288-E8C3-4345-B84D-2E64598DCF3A}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/vsprojects/coapp/zlib/zlib.vcxproj b/vsprojects/coapp/zlib/zlib.vcxproj
new file mode 100644
index 0000000000..56df39a248
--- /dev/null
+++ b/vsprojects/coapp/zlib/zlib.vcxproj
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="PreBuildCmds;PreBuildTargets;Build;PostBuildCmds;PostBuildTargets" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="CoApp" >
+ <CoAppEtcDirectory>$(registry:HKEY_LOCAL_MACHINE\Software\Outercurve\CoApp.Powershell\etc)</CoAppEtcDirectory>
+
+ <!-- Set to true to make visual studio use PTK when building.-->
+ <UsePTKFromVisualStudio>false</UsePTKFromVisualStudio>
+ </PropertyGroup>
+
+ <PropertyGroup Label="Configuration" >
+ <!-- This lets Visual Studio see this as a VC12 project by default -->
+ <PlatformToolset Condition="'$(PlatformToolset)' == ''">v120</PlatformToolset>
+ </PropertyGroup>
+
+ <Import Condition="Exists('$(CoAppEtcDirectory)\common-variables.vcxproj')" Project="$(CoAppEtcDirectory)\common-variables.vcxproj" />
+
+ <PropertyGroup Label="CustomSettings" />
+
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{63BED288-E8C3-4345-B84D-2E64598DCF3A}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+
+ <OutNameSuffix Condition="$(IS_CDECL) AND $(IS_DYNAMIC)">1</OutNameSuffix>
+
+ <!-- set to Application or DynamicLibrary (DynamicLibrary can get altered to StaticLibrary by PTK -->
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+
+ <!-- Common Compiler Defines (semicolon delimited) -->
+ <Defines>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;</Defines>
+ <Defines Condition="$(IS_STDCALL)">$(Defines);ZLIB_WINAPI;</Defines>
+ <Defines Condition="$(IS_DYNAMIC)">$(Defines);ZLIB_DLL;</Defines>
+ <Defines Condition="'$(AppContainer)' == 'App'">$(Defines);IOWIN32_USING_WINRT_API=1;</Defines>
+ <Defines Condition="'$(AppContainer)' != 'App'">$(Defines);IOWIN32_USING_WINRT_API=0;</Defines>
+ <Defines Condition="'$(UseASM)' == 'ASM'">$(Defines);ASMV;ASMINF;</Defines>
+ <Defines Condition="$(IS_X64)">$(Defines);WIN64;</Defines>
+
+ <!-- Additional Include folders (semicolon delimited) -->
+ <IncludeDirectories>..\..\..\third_party\zlib;</IncludeDirectories>
+
+ <!-- Additional Library folders (semicolon delimited) -->
+ <LibraryDirectories></LibraryDirectories>
+
+ <!-- Libraries to Link with -->
+ <Libraries></Libraries>
+
+ <!-- Batch script to run before Build-->
+ <PreBuild></PreBuild>
+
+ <!-- Batch script to run after Build-->
+ <PostBuild></PostBuild>
+
+ <!-- Batch script to run before Link step-->
+ <PreLink></PreLink>
+
+ <!-- Batch script to run after Link-->
+ <PostLink></PostLink>
+
+ <!-- Batch script to run before Lib step-->
+ <PreLib></PreLib>
+
+ <!-- Batch script to run after Lib-->
+ <PostLib></PostLib>
+
+ <!-- Targets to run before Build (semcolon delimited)-->
+ <PreBuildTargets></PreBuildTargets>
+
+ <!-- Targets to run before Build (semcolon delimited)-->
+ <PostBuildTargets></PostBuildTargets>
+
+ <!-- for Dynamic libs, you can specify the Module .DEF file path -->
+ <ModuleDefinitionFile></ModuleDefinitionFile>
+ </PropertyGroup>
+
+ <Import Condition="Exists('$(CoAppEtcDirectory)\common-header.vcxproj')" Project="$(CoAppEtcDirectory)\common-header.vcxproj" />
+ <Import Condition="'$(UseASM)' == 'ASM'" Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
+
+ <PropertyGroup>
+ <OutDir>$(ProjectRootDir)Output/$(PlatformToolset)/$(Platform)/$(Configuration)/$(UsesConfigurationType)/$(CallingConvention)/$(CharacterSet)/$(AppContainer)/$(UseASM)/</OutDir>
+ <IntDir>$(ProjectRootDir)Intermediate/$(TargetName)/$(PlatformToolset)/$(Platform)/$(Configuration)/$(UsesConfigurationType)/$(CallingConvention)/$(CharacterSet)/$(AppContainer)/$(UseASM)/</IntDir>
+ </PropertyGroup>
+
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <BaseAddress>0x5A4C0000</BaseAddress>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemGroup Condition="'$(UseASM)' == 'ASM'">
+ <MASM Include="..\..\..\third_party\zlib\contrib\masmx64\gvmat64.asm" Condition="$(IS_X64)">
+ <AssembledCodeListingFile>$(IntDir)gvmat64.lst</AssembledCodeListingFile>
+ <MASMBeforeTargets>Build</MASMBeforeTargets>
+ <ObjectFileName>$(IntDir)gvmat64.obj</ObjectFileName>
+ </MASM>
+ <MASM Include="..\..\..\third_party\zlib\contrib\masmx64\inffasx64.asm" Condition="$(IS_X64)">
+ <AssembledCodeListingFile>$(IntDir)inffasx64.lst</AssembledCodeListingFile>
+ <MASMBeforeTargets>Build</MASMBeforeTargets>
+ <ObjectFileName>$(IntDir)inffasx64.obj</ObjectFileName>
+ </MASM>
+ <MASM Include="..\..\..\third_party\zlib\contrib\masmx86\inffas32.asm" Condition="$(IS_X86) AND $(IS_STDCALL)">
+ <AssembledCodeListingFile>$(IntDir)inffas32.lst</AssembledCodeListingFile>
+ <MASMBeforeTargets>Build</MASMBeforeTargets>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ <AdditionalOptions>/coff %(AdditionalOptions)</AdditionalOptions>
+ <ObjectFileName>$(IntDir)inffas32.obj</ObjectFileName>
+ </MASM>
+ <MASM Include="..\..\..\third_party\zlib\contrib\masmx86\match686.asm" Condition="$(IS_X86) AND $(IS_STDCALL)">
+ <AssembledCodeListingFile>$(IntDir)match686.lst</AssembledCodeListingFile>
+ <MASMBeforeTargets>Build</MASMBeforeTargets>
+ <UseSafeExceptionHandlers>true</UseSafeExceptionHandlers>
+ <AdditionalOptions>/coff %(AdditionalOptions)</AdditionalOptions>
+ <ObjectFileName>$(IntDir)match686.obj</ObjectFileName>
+ </MASM>
+ </ItemGroup>
+
+ <ItemGroup Label="C Source Files">
+ <!-- Include the source files to compile here -->
+ <!-- <ClCompile Include="..\src\foo.c" /> -->
+ <ClCompile Include="..\..\..\third_party\zlib\adler32.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\compress.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\crc32.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\deflate.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\gzclose.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\gzlib.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\gzread.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\gzwrite.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\infback.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\contrib\masmx64\inffas8664.c" Condition="$(IS_X64)" />
+ <ClCompile Include="..\..\..\third_party\zlib\inffast.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\inflate.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\inftrees.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\trees.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\uncompr.c" />
+ <ClCompile Include="..\..\..\third_party\zlib\zutil.c" />
+ </ItemGroup>
+
+ <ItemGroup Label="Resource Files">
+ <!-- Include the source files to compile here -->
+ <!-- <ResourceCompile Include="..\src\foo.rc" /> -->
+ <ResourceCompile Include="..\..\..\third_party\zlib\win32\zlib1.rc" />
+ </ItemGroup>
+
+ <Import Condition="'$(UseASM)' == 'ASM'" Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
+ <Import Condition="Exists('$(CoAppEtcDirectory)\common-footer.vcxproj')" Project="$(CoAppEtcDirectory)\common-footer.vcxproj" />
+</Project>