aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/core/end2end
diff options
context:
space:
mode:
authorGravatar Mark D. Roth <roth@google.com>2016-11-03 09:33:36 -0700
committerGravatar Mark D. Roth <roth@google.com>2016-11-03 09:33:36 -0700
commite5b4d4f35b9a5ee4e1553cc3cdc136af9992e334 (patch)
tree56582ba7b65bb6fe0f1d8728bfae59e474a4e3e5 /test/core/end2end
parentb2d24886196c5000cc15bb5953659ff50b09ad87 (diff)
parentb37ace5d279925ecd7f8dd6dca03e20cb066ae50 (diff)
Merge remote-tracking branch 'upstream/master' into channel_info_api
Diffstat (limited to 'test/core/end2end')
-rw-r--r--test/core/end2end/end2end_nosec_tests.c8
-rw-r--r--test/core/end2end/end2end_tests.c8
-rw-r--r--test/core/end2end/fixtures/h2_sockpair+trace.c4
-rw-r--r--test/core/end2end/fixtures/h2_sockpair.c4
-rw-r--r--test/core/end2end/fixtures/h2_sockpair_1byte.c4
-rw-r--r--test/core/end2end/fixtures/http_proxy.c10
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer.c16
-rw-r--r--test/core/end2end/fuzzers/client_fuzzer.c6
-rw-r--r--test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_1_headerbin0 -> 18 bytes
-rw-r--r--test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_2_header2bin0 -> 27 bytes
-rwxr-xr-xtest/core/end2end/fuzzers/generate_client_examples_of_bad_closing_streams.py49
-rw-r--r--test/core/end2end/fuzzers/server_fuzzer.c6
-rwxr-xr-xtest/core/end2end/gen_build_yaml.py24
-rw-r--r--test/core/end2end/tests/max_message_length.c1
-rw-r--r--test/core/end2end/tests/network_status_change.c1
-rw-r--r--test/core/end2end/tests/resource_quota_server.c380
16 files changed, 497 insertions, 24 deletions
diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c
index a630262197..caaa97c215 100644
--- a/test/core/end2end/end2end_nosec_tests.c
+++ b/test/core/end2end/end2end_nosec_tests.c
@@ -111,6 +111,8 @@ extern void request_with_flags(grpc_end2end_test_config config);
extern void request_with_flags_pre_init(void);
extern void request_with_payload(grpc_end2end_test_config config);
extern void request_with_payload_pre_init(void);
+extern void resource_quota_server(grpc_end2end_test_config config);
+extern void resource_quota_server_pre_init(void);
extern void server_finishes_request(grpc_end2end_test_config config);
extern void server_finishes_request_pre_init(void);
extern void shutdown_finishes_calls(grpc_end2end_test_config config);
@@ -167,6 +169,7 @@ void grpc_end2end_tests_pre_init(void) {
registered_call_pre_init();
request_with_flags_pre_init();
request_with_payload_pre_init();
+ resource_quota_server_pre_init();
server_finishes_request_pre_init();
shutdown_finishes_calls_pre_init();
shutdown_finishes_tags_pre_init();
@@ -219,6 +222,7 @@ void grpc_end2end_tests(int argc, char **argv,
registered_call(config);
request_with_flags(config);
request_with_payload(config);
+ resource_quota_server(config);
server_finishes_request(config);
shutdown_finishes_calls(config);
shutdown_finishes_tags(config);
@@ -368,6 +372,10 @@ void grpc_end2end_tests(int argc, char **argv,
request_with_payload(config);
continue;
}
+ if (0 == strcmp("resource_quota_server", argv[i])) {
+ resource_quota_server(config);
+ continue;
+ }
if (0 == strcmp("server_finishes_request", argv[i])) {
server_finishes_request(config);
continue;
diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c
index 925872a71f..6d17e686e6 100644
--- a/test/core/end2end/end2end_tests.c
+++ b/test/core/end2end/end2end_tests.c
@@ -113,6 +113,8 @@ extern void request_with_flags(grpc_end2end_test_config config);
extern void request_with_flags_pre_init(void);
extern void request_with_payload(grpc_end2end_test_config config);
extern void request_with_payload_pre_init(void);
+extern void resource_quota_server(grpc_end2end_test_config config);
+extern void resource_quota_server_pre_init(void);
extern void server_finishes_request(grpc_end2end_test_config config);
extern void server_finishes_request_pre_init(void);
extern void shutdown_finishes_calls(grpc_end2end_test_config config);
@@ -170,6 +172,7 @@ void grpc_end2end_tests_pre_init(void) {
registered_call_pre_init();
request_with_flags_pre_init();
request_with_payload_pre_init();
+ resource_quota_server_pre_init();
server_finishes_request_pre_init();
shutdown_finishes_calls_pre_init();
shutdown_finishes_tags_pre_init();
@@ -223,6 +226,7 @@ void grpc_end2end_tests(int argc, char **argv,
registered_call(config);
request_with_flags(config);
request_with_payload(config);
+ resource_quota_server(config);
server_finishes_request(config);
shutdown_finishes_calls(config);
shutdown_finishes_tags(config);
@@ -376,6 +380,10 @@ void grpc_end2end_tests(int argc, char **argv,
request_with_payload(config);
continue;
}
+ if (0 == strcmp("resource_quota_server", argv[i])) {
+ resource_quota_server(config);
+ continue;
+ }
if (0 == strcmp("server_finishes_request", argv[i])) {
server_finishes_request(config);
continue;
diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c
index 15b045c33c..a358edf321 100644
--- a/test/core/end2end/fixtures/h2_sockpair+trace.c
+++ b/test/core/end2end/fixtures/h2_sockpair+trace.c
@@ -96,7 +96,9 @@ static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
f.fixture_data = sfd;
f.cq = grpc_completion_queue_create(NULL);
- *sfd = grpc_iomgr_create_endpoint_pair("fixture", 65536);
+ grpc_resource_quota *resource_quota = grpc_resource_quota_create("fixture");
+ *sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 65536);
+ grpc_resource_quota_unref(resource_quota);
return f;
}
diff --git a/test/core/end2end/fixtures/h2_sockpair.c b/test/core/end2end/fixtures/h2_sockpair.c
index 87091f77a3..8f7083af59 100644
--- a/test/core/end2end/fixtures/h2_sockpair.c
+++ b/test/core/end2end/fixtures/h2_sockpair.c
@@ -90,7 +90,9 @@ static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
f.fixture_data = sfd;
f.cq = grpc_completion_queue_create(NULL);
- *sfd = grpc_iomgr_create_endpoint_pair("fixture", 65536);
+ grpc_resource_quota *resource_quota = grpc_resource_quota_create("fixture");
+ *sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 65536);
+ grpc_resource_quota_unref(resource_quota);
return f;
}
diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c
index 7d0a14cd63..b3d9924c12 100644
--- a/test/core/end2end/fixtures/h2_sockpair_1byte.c
+++ b/test/core/end2end/fixtures/h2_sockpair_1byte.c
@@ -90,7 +90,9 @@ static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
f.fixture_data = sfd;
f.cq = grpc_completion_queue_create(NULL);
- *sfd = grpc_iomgr_create_endpoint_pair("fixture", 1);
+ grpc_resource_quota *resource_quota = grpc_resource_quota_create("fixture");
+ *sfd = grpc_iomgr_create_endpoint_pair("fixture", resource_quota, 1);
+ grpc_resource_quota_unref(resource_quota);
return f;
}
diff --git a/test/core/end2end/fixtures/http_proxy.c b/test/core/end2end/fixtures/http_proxy.c
index b8f046c7df..630f47ef0e 100644
--- a/test/core/end2end/fixtures/http_proxy.c
+++ b/test/core/end2end/fixtures/http_proxy.c
@@ -359,7 +359,7 @@ static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg,
const gpr_timespec deadline = gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(10, GPR_TIMESPAN));
grpc_tcp_client_connect(exec_ctx, &conn->on_server_connect_done,
- &conn->server_endpoint, conn->pollset_set,
+ &conn->server_endpoint, conn->pollset_set, NULL,
&resolved_addresses->addrs[0], deadline);
grpc_resolved_addresses_destroy(resolved_addresses);
}
@@ -418,7 +418,8 @@ static void thread_main(void* arg) {
grpc_exec_ctx_finish(&exec_ctx);
}
-grpc_end2end_http_proxy* grpc_end2end_http_proxy_create() {
+grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_end2end_http_proxy* proxy = gpr_malloc(sizeof(*proxy));
memset(proxy, 0, sizeof(*proxy));
// Construct proxy address.
@@ -427,8 +428,8 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create() {
gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name);
// Create TCP server.
proxy->channel_args = grpc_channel_args_copy(NULL);
- grpc_error* error =
- grpc_tcp_server_create(NULL, proxy->channel_args, &proxy->server);
+ grpc_error* error = grpc_tcp_server_create(
+ &exec_ctx, NULL, proxy->channel_args, &proxy->server);
GPR_ASSERT(error == GRPC_ERROR_NONE);
// Bind to port.
grpc_resolved_address resolved_addr;
@@ -443,7 +444,6 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create() {
// Start server.
proxy->pollset = gpr_malloc(grpc_pollset_size());
grpc_pollset_init(proxy->pollset, &proxy->mu);
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_tcp_server_start(&exec_ctx, proxy->server, &proxy->pollset, 1, on_accept,
proxy);
grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index 4e19b76014..659f5cf5cb 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -173,6 +173,7 @@ static bool is_eof(input_stream *inp) { return inp->cur == inp->end; }
static gpr_timespec g_now;
static grpc_server *g_server;
static grpc_channel *g_channel;
+static grpc_resource_quota *g_resource_quota;
extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type);
@@ -231,8 +232,8 @@ void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr,
// defined in tcp_client_posix.c
extern void (*grpc_tcp_client_connect_impl)(
grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
- grpc_pollset_set *interested_parties, const grpc_resolved_address *addr,
- gpr_timespec deadline);
+ grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args,
+ const grpc_resolved_address *addr, gpr_timespec deadline);
static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_endpoint **ep, gpr_timespec deadline);
@@ -252,7 +253,7 @@ static void do_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
} else if (g_server != NULL) {
grpc_endpoint *client;
grpc_endpoint *server;
- grpc_passthru_endpoint_create(&client, &server);
+ grpc_passthru_endpoint_create(&client, &server, g_resource_quota);
*fc->ep = client;
grpc_transport *transport =
@@ -289,6 +290,7 @@ static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
static void my_tcp_client_connect(grpc_exec_ctx *exec_ctx,
grpc_closure *closure, grpc_endpoint **ep,
grpc_pollset_set *interested_parties,
+ const grpc_channel_args *channel_args,
const grpc_resolved_address *addr,
gpr_timespec deadline) {
sched_connect(exec_ctx, closure, ep, deadline);
@@ -520,6 +522,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
int pending_pings = 0;
g_active_call = new_call(NULL, ROOT);
+ g_resource_quota = grpc_resource_quota_create("api_fuzzer");
grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
@@ -939,6 +942,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
break;
}
+ // resize the buffer pool
+ case 21: {
+ grpc_resource_quota_resize(g_resource_quota, read_uint22(&inp));
+ break;
+ }
}
}
@@ -954,6 +962,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
.type == GRPC_QUEUE_SHUTDOWN);
grpc_completion_queue_destroy(cq);
+ grpc_resource_quota_unref(g_resource_quota);
+
grpc_shutdown();
return 0;
}
diff --git a/test/core/end2end/fuzzers/client_fuzzer.c b/test/core/end2end/fuzzers/client_fuzzer.c
index 00e650a30b..d104fe55e5 100644
--- a/test/core/end2end/fuzzers/client_fuzzer.c
+++ b/test/core/end2end/fuzzers/client_fuzzer.c
@@ -58,7 +58,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
grpc_init();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_endpoint *mock_endpoint = grpc_mock_endpoint_create(discard_write);
+ grpc_resource_quota *resource_quota =
+ grpc_resource_quota_create("client_fuzzer");
+ grpc_endpoint *mock_endpoint =
+ grpc_mock_endpoint_create(discard_write, resource_quota);
+ grpc_resource_quota_internal_unref(&exec_ctx, resource_quota);
grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
grpc_transport *transport =
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_1_header b/test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_1_header
new file mode 100644
index 0000000000..d2abd17464
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_1_header
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_2_header2 b/test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_2_header2
new file mode 100644
index 0000000000..752af468ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/server_hanging_response_2_header2
Binary files differ
diff --git a/test/core/end2end/fuzzers/generate_client_examples_of_bad_closing_streams.py b/test/core/end2end/fuzzers/generate_client_examples_of_bad_closing_streams.py
new file mode 100755
index 0000000000..d80c1e0442
--- /dev/null
+++ b/test/core/end2end/fuzzers/generate_client_examples_of_bad_closing_streams.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python2.7
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import sys
+
+os.chdir(os.path.dirname(sys.argv[0]))
+
+streams = {
+ 'server_hanging_response_1_header': (
+ [0,0,0,4,0,0,0,0,0] + # settings frame
+ [0,0,0,1,5,0,0,0,1] # trailers
+ ),
+ 'server_hanging_response_2_header2': (
+ [0,0,0,4,0,0,0,0,0] + # settings frame
+ [0,0,0,1,4,0,0,0,1] + # headers
+ [0,0,0,1,5,0,0,0,1] # trailers
+ ),
+}
+
+for name, stream in streams.items():
+ open('client_fuzzer_corpus/%s' % name, 'w').write(bytearray(stream))
diff --git a/test/core/end2end/fuzzers/server_fuzzer.c b/test/core/end2end/fuzzers/server_fuzzer.c
index 79eaad70c5..ae4c8e658d 100644
--- a/test/core/end2end/fuzzers/server_fuzzer.c
+++ b/test/core/end2end/fuzzers/server_fuzzer.c
@@ -56,7 +56,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
grpc_init();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_endpoint *mock_endpoint = grpc_mock_endpoint_create(discard_write);
+ grpc_resource_quota *resource_quota =
+ grpc_resource_quota_create("server_fuzzer");
+ grpc_endpoint *mock_endpoint =
+ grpc_mock_endpoint_create(discard_write, resource_quota);
+ grpc_resource_quota_internal_unref(&exec_ctx, resource_quota);
grpc_mock_endpoint_put_read(
&exec_ctx, mock_endpoint,
gpr_slice_from_copied_buffer((const char *)data, size));
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index 0bbf10d475..bdb3874c21 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -39,9 +39,9 @@ import hashlib
FixtureOptions = collections.namedtuple(
'FixtureOptions',
- 'fullstack includes_proxy dns_resolver secure platforms ci_mac tracing exclude_configs exclude_iomgrs')
+ 'fullstack includes_proxy dns_resolver secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes')
default_unsecure_fixture_options = FixtureOptions(
- True, False, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [])
+ True, False, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [], True)
socketpair_unsecure_fixture_options = default_unsecure_fixture_options._replace(fullstack=False, dns_resolver=False)
default_secure_fixture_options = default_unsecure_fixture_options._replace(secure=True)
uds_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, platforms=['linux', 'mac', 'posix'], exclude_iomgrs=['uv'])
@@ -69,11 +69,12 @@ END2END_FIXTURES = {
'h2_proxy': default_unsecure_fixture_options._replace(
includes_proxy=True, ci_mac=False, exclude_iomgrs=['uv']),
'h2_sockpair_1byte': socketpair_unsecure_fixture_options._replace(
- ci_mac=False, exclude_configs=['msan'], exclude_iomgrs=['uv']),
+ ci_mac=False, exclude_configs=['msan'], large_writes=False,
+ exclude_iomgrs=['uv']),
'h2_sockpair': socketpair_unsecure_fixture_options._replace(
ci_mac=False, exclude_iomgrs=['uv']),
'h2_sockpair+trace': socketpair_unsecure_fixture_options._replace(
- ci_mac=False, tracing=True, exclude_iomgrs=['uv']),
+ ci_mac=False, tracing=True, large_writes=False, exclude_iomgrs=['uv']),
'h2_ssl': default_secure_fixture_options,
'h2_ssl_cert': default_secure_fixture_options,
'h2_ssl_proxy': default_secure_fixture_options._replace(
@@ -83,8 +84,8 @@ END2END_FIXTURES = {
TestOptions = collections.namedtuple(
'TestOptions',
- 'needs_fullstack needs_dns proxyable secure traceable cpu_cost exclude_iomgrs')
-default_test_options = TestOptions(False, False, True, False, True, 1.0, [])
+ 'needs_fullstack needs_dns proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky')
+default_test_options = TestOptions(False, False, True, False, True, 1.0, [], False, False)
connectivity_test_options = default_test_options._replace(needs_fullstack=True)
LOWCPU = 0.1
@@ -93,6 +94,8 @@ LOWCPU = 0.1
END2END_TESTS = {
'bad_hostname': default_test_options,
'binary_metadata': default_test_options,
+ 'resource_quota_server': default_test_options._replace(large_writes=True,
+ proxyable=False),
'call_creds': default_test_options._replace(secure=True),
'cancel_after_accept': default_test_options._replace(cpu_cost=LOWCPU),
'cancel_after_client_done': default_test_options,
@@ -105,7 +108,7 @@ END2END_TESTS = {
proxyable=False, cpu_cost=LOWCPU, exclude_iomgrs=['uv']),
'default_host': default_test_options._replace(needs_fullstack=True,
needs_dns=True),
- 'disappearing_server': connectivity_test_options,
+ 'disappearing_server': connectivity_test_options._replace(flaky=True),
'empty_batch': default_test_options,
'filter_causes_close': default_test_options,
'filter_call_init_fails': default_test_options,
@@ -155,6 +158,9 @@ def compatible(f, t):
if not END2END_TESTS[t].traceable:
if END2END_FIXTURES[f].tracing:
return False
+ if END2END_TESTS[t].large_writes:
+ if not END2END_FIXTURES[f].large_writes:
+ return False
return True
@@ -257,7 +263,7 @@ def main():
'ci_platforms': (END2END_FIXTURES[f].platforms
if END2END_FIXTURES[f].ci_mac else without(
END2END_FIXTURES[f].platforms, 'mac')),
- 'flaky': False,
+ 'flaky': END2END_TESTS[t].flaky,
'language': 'c',
'cpu_cost': END2END_TESTS[t].cpu_cost,
}
@@ -274,7 +280,7 @@ def main():
'ci_platforms': (END2END_FIXTURES[f].platforms
if END2END_FIXTURES[f].ci_mac else without(
END2END_FIXTURES[f].platforms, 'mac')),
- 'flaky': False,
+ 'flaky': END2END_TESTS[t].flaky,
'language': 'c',
'cpu_cost': END2END_TESTS[t].cpu_cost,
}
diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c
index e698987a0a..449a581d23 100644
--- a/test/core/end2end/tests/max_message_length.c
+++ b/test/core/end2end/tests/max_message_length.c
@@ -402,7 +402,6 @@ static void test_max_message_length_on_response(grpc_end2end_test_config config,
GPR_ASSERT(0 == strcmp(call_details.method, "/service/method"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234"));
- GPR_ASSERT(was_cancelled == 0);
GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
GPR_ASSERT(strcmp(details,
diff --git a/test/core/end2end/tests/network_status_change.c b/test/core/end2end/tests/network_status_change.c
index 8d6b8f8784..fa711bb0b6 100644
--- a/test/core/end2end/tests/network_status_change.c
+++ b/test/core/end2end/tests/network_status_change.c
@@ -213,7 +213,6 @@ static void test_invoke_network_status_change(grpc_end2end_test_config config) {
GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
- GPR_ASSERT(was_cancelled == 0);
gpr_free(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c
new file mode 100644
index 0000000000..47c5ed6abb
--- /dev/null
+++ b/test/core/end2end/tests/resource_quota_server.c
@@ -0,0 +1,380 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include "test/core/end2end/cq_verifier.h"
+
+static void *tag(intptr_t t) { return (void *)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+ const char *test_name,
+ grpc_channel_args *client_args,
+ grpc_channel_args *server_args) {
+ grpc_end2end_test_fixture f;
+ gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+ f = config.create_fixture(client_args, server_args);
+ config.init_server(&f, server_args);
+ config.init_client(&f, client_args, NULL);
+ return f;
+}
+
+static gpr_timespec n_seconds_time(int n) {
+ return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+}
+
+static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
+
+static void drain_cq(grpc_completion_queue *cq) {
+ grpc_event ev;
+ do {
+ ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL);
+ } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture *f) {
+ if (!f->server) return;
+ grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
+ GPR_ASSERT(grpc_completion_queue_pluck(
+ f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+ .type == GRPC_OP_COMPLETE);
+ grpc_server_destroy(f->server);
+ f->server = NULL;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture *f) {
+ if (!f->client) return;
+ grpc_channel_destroy(f->client);
+ f->client = NULL;
+}
+
+static void end_test(grpc_end2end_test_fixture *f) {
+ shutdown_server(f);
+ shutdown_client(f);
+
+ grpc_completion_queue_shutdown(f->cq);
+ drain_cq(f->cq);
+ grpc_completion_queue_destroy(f->cq);
+}
+
+/* Creates and returns a gpr_slice containing random alphanumeric characters. */
+static gpr_slice generate_random_slice() {
+ size_t i;
+ static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890";
+ char *output;
+ const size_t output_size = 1024 * 1024;
+ output = gpr_malloc(output_size);
+ for (i = 0; i < output_size - 1; ++i) {
+ output[i] = chars[rand() % (int)(sizeof(chars) - 1)];
+ }
+ output[output_size - 1] = '\0';
+ gpr_slice out = gpr_slice_from_copied_string(output);
+ gpr_free(output);
+ return out;
+}
+
+void resource_quota_server(grpc_end2end_test_config config) {
+ grpc_resource_quota *resource_quota =
+ grpc_resource_quota_create("test_server");
+ grpc_resource_quota_resize(resource_quota, 5 * 1024 * 1024);
+
+#define NUM_CALLS 100
+#define CLIENT_BASE_TAG 1000
+#define SERVER_START_BASE_TAG 2000
+#define SERVER_RECV_BASE_TAG 3000
+#define SERVER_END_BASE_TAG 4000
+
+ grpc_arg arg;
+ arg.key = GRPC_ARG_RESOURCE_QUOTA;
+ arg.type = GRPC_ARG_POINTER;
+ arg.value.pointer.p = resource_quota;
+ arg.value.pointer.vtable = grpc_resource_quota_arg_vtable();
+ grpc_channel_args args = {1, &arg};
+
+ grpc_end2end_test_fixture f =
+ begin_test(config, "resource_quota_server", NULL, &args);
+
+ /* Create large request and response bodies. These are big enough to require
+ * multiple round trips to deliver to the peer, and their exact contents of
+ * will be verified on completion. */
+ gpr_slice request_payload_slice = generate_random_slice();
+
+ grpc_call **client_calls = malloc(sizeof(grpc_call *) * NUM_CALLS);
+ grpc_call **server_calls = malloc(sizeof(grpc_call *) * NUM_CALLS);
+ grpc_metadata_array *initial_metadata_recv =
+ malloc(sizeof(grpc_metadata_array) * NUM_CALLS);
+ grpc_metadata_array *trailing_metadata_recv =
+ malloc(sizeof(grpc_metadata_array) * NUM_CALLS);
+ grpc_metadata_array *request_metadata_recv =
+ malloc(sizeof(grpc_metadata_array) * NUM_CALLS);
+ grpc_call_details *call_details =
+ malloc(sizeof(grpc_call_details) * NUM_CALLS);
+ grpc_status_code *status = malloc(sizeof(grpc_status_code) * NUM_CALLS);
+ char **details = malloc(sizeof(char *) * NUM_CALLS);
+ size_t *details_capacity = malloc(sizeof(size_t) * NUM_CALLS);
+ grpc_byte_buffer **request_payload_recv =
+ malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS);
+ int *was_cancelled = malloc(sizeof(int) * NUM_CALLS);
+ grpc_call_error error;
+ int pending_client_calls = 0;
+ int pending_server_start_calls = 0;
+ int pending_server_recv_calls = 0;
+ int pending_server_end_calls = 0;
+ int cancelled_calls_on_client = 0;
+ int cancelled_calls_on_server = 0;
+
+ grpc_byte_buffer *request_payload =
+ grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+
+ grpc_op ops[6];
+ grpc_op *op;
+
+ for (int i = 0; i < NUM_CALLS; i++) {
+ grpc_metadata_array_init(&initial_metadata_recv[i]);
+ grpc_metadata_array_init(&trailing_metadata_recv[i]);
+ grpc_metadata_array_init(&request_metadata_recv[i]);
+ grpc_call_details_init(&call_details[i]);
+ details[i] = NULL;
+ details_capacity[i] = 0;
+ request_payload_recv[i] = NULL;
+ was_cancelled[i] = 0;
+ }
+
+ for (int i = 0; i < NUM_CALLS; i++) {
+ error = grpc_server_request_call(
+ f.server, &server_calls[i], &call_details[i], &request_metadata_recv[i],
+ f.cq, f.cq, tag(SERVER_START_BASE_TAG + i));
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
+ pending_server_start_calls++;
+ }
+
+ for (int i = 0; i < NUM_CALLS; i++) {
+ client_calls[i] = grpc_channel_create_call(
+ f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
+ "foo.test.google.fr", n_seconds_time(60), NULL);
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->data.send_initial_metadata.count = 0;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_SEND_MESSAGE;
+ op->data.send_message = request_payload;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_RECV_INITIAL_METADATA;
+ op->data.recv_initial_metadata = &initial_metadata_recv[i];
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+ op->data.recv_status_on_client.trailing_metadata =
+ &trailing_metadata_recv[i];
+ op->data.recv_status_on_client.status = &status[i];
+ op->data.recv_status_on_client.status_details = &details[i];
+ op->data.recv_status_on_client.status_details_capacity =
+ &details_capacity[i];
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ error = grpc_call_start_batch(client_calls[i], ops, (size_t)(op - ops),
+ tag(CLIENT_BASE_TAG + i), NULL);
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
+ pending_client_calls++;
+ }
+
+ while (pending_client_calls + pending_server_recv_calls +
+ pending_server_end_calls >
+ 0) {
+ grpc_event ev = grpc_completion_queue_next(f.cq, n_seconds_time(10), NULL);
+ GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+
+ int ev_tag = (int)(intptr_t)ev.tag;
+ if (ev_tag < CLIENT_BASE_TAG) {
+ abort(); /* illegal tag */
+ } else if (ev_tag < SERVER_START_BASE_TAG) {
+ /* client call finished */
+ int call_id = ev_tag - CLIENT_BASE_TAG;
+ GPR_ASSERT(call_id >= 0);
+ GPR_ASSERT(call_id < NUM_CALLS);
+ switch (status[call_id]) {
+ case GRPC_STATUS_RESOURCE_EXHAUSTED:
+ cancelled_calls_on_client++;
+ break;
+ case GRPC_STATUS_OK:
+ break;
+ default:
+ gpr_log(GPR_ERROR, "Unexpected status code: %d", status[call_id]);
+ abort();
+ }
+ GPR_ASSERT(pending_client_calls > 0);
+
+ grpc_metadata_array_destroy(&initial_metadata_recv[call_id]);
+ grpc_metadata_array_destroy(&trailing_metadata_recv[call_id]);
+ grpc_call_destroy(client_calls[call_id]);
+ gpr_free(details[call_id]);
+
+ pending_client_calls--;
+ } else if (ev_tag < SERVER_RECV_BASE_TAG) {
+ /* new incoming call to the server */
+ int call_id = ev_tag - SERVER_START_BASE_TAG;
+ GPR_ASSERT(call_id >= 0);
+ GPR_ASSERT(call_id < NUM_CALLS);
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->data.send_initial_metadata.count = 0;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_RECV_MESSAGE;
+ op->data.recv_message = &request_payload_recv[call_id];
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ error =
+ grpc_call_start_batch(server_calls[call_id], ops, (size_t)(op - ops),
+ tag(SERVER_RECV_BASE_TAG + call_id), NULL);
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
+ GPR_ASSERT(pending_server_start_calls > 0);
+ pending_server_start_calls--;
+ pending_server_recv_calls++;
+
+ grpc_call_details_destroy(&call_details[call_id]);
+ grpc_metadata_array_destroy(&request_metadata_recv[call_id]);
+ } else if (ev_tag < SERVER_END_BASE_TAG) {
+ /* finished read on the server */
+ int call_id = ev_tag - SERVER_RECV_BASE_TAG;
+ GPR_ASSERT(call_id >= 0);
+ GPR_ASSERT(call_id < NUM_CALLS);
+
+ if (ev.success) {
+ if (request_payload_recv[call_id] != NULL) {
+ grpc_byte_buffer_destroy(request_payload_recv[call_id]);
+ request_payload_recv[call_id] = NULL;
+ }
+ } else {
+ GPR_ASSERT(request_payload_recv[call_id] == NULL);
+ }
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+ op->data.recv_close_on_server.cancelled = &was_cancelled[call_id];
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+ op->data.send_status_from_server.trailing_metadata_count = 0;
+ op->data.send_status_from_server.status = GRPC_STATUS_OK;
+ op->data.send_status_from_server.status_details = "xyz";
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ error =
+ grpc_call_start_batch(server_calls[call_id], ops, (size_t)(op - ops),
+ tag(SERVER_END_BASE_TAG + call_id), NULL);
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
+ GPR_ASSERT(pending_server_recv_calls > 0);
+ pending_server_recv_calls--;
+ pending_server_end_calls++;
+ } else {
+ int call_id = ev_tag - SERVER_END_BASE_TAG;
+ GPR_ASSERT(call_id >= 0);
+ GPR_ASSERT(call_id < NUM_CALLS);
+
+ if (was_cancelled[call_id]) {
+ cancelled_calls_on_server++;
+ }
+ GPR_ASSERT(pending_server_end_calls > 0);
+ pending_server_end_calls--;
+
+ grpc_call_destroy(server_calls[call_id]);
+ }
+ }
+
+ gpr_log(
+ GPR_INFO,
+ "Done. %d total calls: %d cancelled at server, %d cancelled at client.",
+ NUM_CALLS, cancelled_calls_on_server, cancelled_calls_on_client);
+
+ /* The call may be cancelled after the server has sent its status but before
+ * the client has received it. This means that we should see strictly more
+ * failures on the client than on the server. */
+ GPR_ASSERT(cancelled_calls_on_client >= cancelled_calls_on_server);
+ /* However, we shouldn't see radically more... 0.9 is a guessed bound on what
+ * we'd want that ratio to be... to at least trigger some investigation should
+ * that ratio become much higher. */
+ GPR_ASSERT(cancelled_calls_on_server >= 0.9 * cancelled_calls_on_client);
+
+ grpc_byte_buffer_destroy(request_payload);
+ gpr_slice_unref(request_payload_slice);
+ grpc_resource_quota_unref(resource_quota);
+
+ free(client_calls);
+ free(server_calls);
+ free(initial_metadata_recv);
+ free(trailing_metadata_recv);
+ free(request_metadata_recv);
+ free(call_details);
+ free(status);
+ free(details);
+ free(details_capacity);
+ free(request_payload_recv);
+ free(was_cancelled);
+
+ end_test(&f);
+ config.tear_down_data(&f);
+}
+
+void resource_quota_server_pre_init(void) {}