aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/core/bad_client/bad_client.c3
-rwxr-xr-xtest/core/bad_client/gen_build_json.py9
-rwxr-xr-xtest/core/end2end/gen_build_json.py34
-rw-r--r--test/core/end2end/multiple_server_queues_test.c62
-rw-r--r--test/core/end2end/tests/invoke_large_request.c2
-rw-r--r--test/core/end2end/tests/request_with_flags.c7
-rw-r--r--test/core/iomgr/fd_conservation_posix_test.c63
-rw-r--r--test/core/security/auth_context_test.c8
-rw-r--r--test/core/security/base64_test.c38
-rw-r--r--test/core/security/fetch_oauth2.c23
-rw-r--r--test/core/security/print_google_default_creds_token.c23
-rw-r--r--test/core/security/security_connector_test.c256
-rw-r--r--test/core/surface/byte_buffer_reader_test.c25
-rw-r--r--test/cpp/end2end/client_crash_test.cc3
-rw-r--r--test/cpp/end2end/end2end_test.cc39
-rw-r--r--test/cpp/end2end/generic_end2end_test.cc2
-rw-r--r--test/cpp/qps/client_async.cc19
-rw-r--r--test/cpp/qps/qps_worker.cc2
-rw-r--r--test/cpp/qps/report.cc16
-rw-r--r--test/cpp/qps/report.h24
-rw-r--r--test/cpp/qps/server_async.cc35
-rw-r--r--test/cpp/qps/worker.cc2
-rw-r--r--test/cpp/util/byte_buffer_test.cc115
-rw-r--r--test/cpp/util/grpc_cli.cc2
-rw-r--r--test/cpp/util/slice_test.cc77
-rw-r--r--test/proto/messages.proto27
-rw-r--r--test/proto/test.proto8
27 files changed, 836 insertions, 88 deletions
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index e9adcf34c7..5b836fefc3 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -41,6 +41,7 @@
#include "src/core/support/string.h"
#include "src/core/transport/chttp2_transport.h"
+#include <grpc/support/alloc.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
@@ -89,6 +90,8 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator,
/* Add a debug log */
gpr_log(GPR_INFO, "TEST: %s", hex);
+ gpr_free(hex);
+
/* Init grpc */
grpc_init();
diff --git a/test/core/bad_client/gen_build_json.py b/test/core/bad_client/gen_build_json.py
index a6fa266bec..33bf65ac04 100755
--- a/test/core/bad_client/gen_build_json.py
+++ b/test/core/bad_client/gen_build_json.py
@@ -54,6 +54,15 @@ def main():
'language': 'c',
'src': [
'test/core/bad_client/bad_client.c'
+ ],
+ 'headers': [
+ 'test/core/bad_client/bad_client.h'
+ ],
+ 'deps': [
+ 'grpc_test_util_unsecure',
+ 'grpc_unsecure',
+ 'gpr_test_util',
+ 'gpr'
]
}],
'targets': [
diff --git a/test/core/end2end/gen_build_json.py b/test/core/end2end/gen_build_json.py
index f47c92bc47..f1c7e85e08 100755
--- a/test/core/end2end/gen_build_json.py
+++ b/test/core/end2end/gen_build_json.py
@@ -93,6 +93,19 @@ END2END_TESTS = {
def main():
+ sec_deps = [
+ 'end2end_certs',
+ 'grpc_test_util',
+ 'grpc',
+ 'gpr_test_util',
+ 'gpr'
+ ]
+ unsec_deps = [
+ 'grpc_test_util_unsecure',
+ 'grpc_unsecure',
+ 'gpr_test_util',
+ 'gpr'
+ ]
json = {
'#': 'generated with test/end2end/gen_build_json.py',
'libs': [
@@ -103,6 +116,8 @@ def main():
'secure': 'check' if END2END_FIXTURES[f].secure else 'no',
'src': ['test/core/end2end/fixtures/%s.c' % f],
'platforms': [ 'posix' ] if f.endswith('_posix') else END2END_FIXTURES[f].platforms,
+ 'deps': sec_deps if END2END_FIXTURES[f].secure else unsec_deps,
+ 'headers': ['test/core/end2end/end2end_tests.h'],
}
for f in sorted(END2END_FIXTURES.keys())] + [
{
@@ -111,7 +126,9 @@ def main():
'language': 'c',
'secure': 'check' if END2END_TESTS[t].secure else 'no',
'src': ['test/core/end2end/tests/%s.c' % t],
- 'headers': ['test/core/end2end/tests/cancel_test_helpers.h']
+ 'headers': ['test/core/end2end/tests/cancel_test_helpers.h',
+ 'test/core/end2end/end2end_tests.h'],
+ 'deps': sec_deps if END2END_TESTS[t].secure else unsec_deps
}
for t in sorted(END2END_TESTS.keys())] + [
{
@@ -135,13 +152,7 @@ def main():
'platforms': END2END_FIXTURES[f].platforms,
'deps': [
'end2end_fixture_%s' % f,
- 'end2end_test_%s' % t,
- 'end2end_certs',
- 'grpc_test_util',
- 'grpc',
- 'gpr_test_util',
- 'gpr'
- ]
+ 'end2end_test_%s' % t] + sec_deps
}
for f in sorted(END2END_FIXTURES.keys())
for t in sorted(END2END_TESTS.keys())] + [
@@ -155,12 +166,7 @@ def main():
'platforms': END2END_FIXTURES[f].platforms,
'deps': [
'end2end_fixture_%s' % f,
- 'end2end_test_%s' % t,
- 'grpc_test_util_unsecure',
- 'grpc_unsecure',
- 'gpr_test_util',
- 'gpr'
- ]
+ 'end2end_test_%s' % t] + unsec_deps
}
for f in sorted(END2END_FIXTURES.keys()) if not END2END_FIXTURES[f].secure
for t in sorted(END2END_TESTS.keys()) if not END2END_TESTS[t].secure]}
diff --git a/test/core/end2end/multiple_server_queues_test.c b/test/core/end2end/multiple_server_queues_test.c
new file mode 100644
index 0000000000..2306015eed
--- /dev/null
+++ b/test/core/end2end/multiple_server_queues_test.c
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/grpc.h>
+#include "test/core/util/test_config.h"
+
+int main(int argc, char **argv) {
+ grpc_completion_queue *cq1;
+ grpc_completion_queue *cq2;
+ grpc_server *server;
+
+ grpc_test_init(argc, argv);
+ grpc_init();
+ cq1 = grpc_completion_queue_create();
+ cq2 = grpc_completion_queue_create();
+ server = grpc_server_create(NULL);
+ grpc_server_register_completion_queue(server, cq1);
+ grpc_server_add_http2_port(server, "[::]:0");
+ grpc_server_register_completion_queue(server, cq2);
+ grpc_server_start(server);
+ grpc_server_shutdown_and_notify(server, cq2, NULL);
+ grpc_completion_queue_next(cq2, gpr_inf_future); /* cue queue hang */
+ grpc_completion_queue_shutdown(cq1);
+ grpc_completion_queue_shutdown(cq2);
+ grpc_completion_queue_next(cq1, gpr_inf_future);
+ grpc_completion_queue_next(cq2, gpr_inf_future);
+ grpc_server_destroy(server);
+ grpc_completion_queue_destroy(cq1);
+ grpc_completion_queue_destroy(cq2);
+ grpc_shutdown();
+ return 0;
+}
diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c
index ae85af980a..744a9ada57 100644
--- a/test/core/end2end/tests/invoke_large_request.c
+++ b/test/core/end2end/tests/invoke_large_request.c
@@ -97,7 +97,7 @@ static void end_test(grpc_end2end_test_fixture *f) {
static gpr_slice large_slice(void) {
gpr_slice slice = gpr_slice_malloc(1000000);
- memset(GPR_SLICE_START_PTR(slice), 0xab, GPR_SLICE_LENGTH(slice));
+ memset(GPR_SLICE_START_PTR(slice), 'x', GPR_SLICE_LENGTH(slice));
return slice;
}
diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c
index fac0602328..fb55a6512f 100644
--- a/test/core/end2end/tests/request_with_flags.c
+++ b/test/core/end2end/tests/request_with_flags.c
@@ -105,7 +105,7 @@ static void test_invoke_request_with_flags(
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
grpc_byte_buffer *request_payload =
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
- gpr_timespec deadline = five_seconds_time();
+ gpr_timespec deadline = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100);
grpc_end2end_test_fixture f =
begin_test(config, "test_invoke_request_with_flags", NULL, NULL);
cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -156,6 +156,11 @@ static void test_invoke_request_with_flags(
expectation = call_start_batch_expected_result;
GPR_ASSERT(expectation == grpc_call_start_batch(c, ops, op - ops, tag(1)));
+ if (expectation == GRPC_CALL_OK) {
+ cq_expect_completion(cqv, tag(1), 1);
+ cq_verify(cqv);
+ }
+
gpr_free(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
diff --git a/test/core/iomgr/fd_conservation_posix_test.c b/test/core/iomgr/fd_conservation_posix_test.c
new file mode 100644
index 0000000000..aa4551f2f1
--- /dev/null
+++ b/test/core/iomgr/fd_conservation_posix_test.c
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/resource.h>
+
+#include <grpc/support/log.h>
+
+#include "test/core/util/test_config.h"
+#include "src/core/iomgr/endpoint_pair.h"
+#include "src/core/iomgr/iomgr.h"
+
+int main(int argc, char **argv) {
+ int i;
+ struct rlimit rlim;
+ grpc_endpoint_pair p;
+ grpc_test_init(argc, argv);
+ grpc_iomgr_init();
+
+ /* set max # of file descriptors to a low value, and
+ verify we can create and destroy many more than this number
+ of descriptors */
+ rlim.rlim_cur = rlim.rlim_max = 10;
+ GPR_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &rlim));
+
+ for (i = 0; i < 100; i++) {
+ p = grpc_iomgr_create_endpoint_pair("test", 1);
+ grpc_endpoint_destroy(p.client);
+ grpc_endpoint_destroy(p.server);
+ }
+
+ grpc_iomgr_shutdown();
+ return 0;
+}
diff --git a/test/core/security/auth_context_test.c b/test/core/security/auth_context_test.c
index 2fb0c01f6f..2b12551a06 100644
--- a/test/core/security/auth_context_test.c
+++ b/test/core/security/auth_context_test.c
@@ -52,7 +52,7 @@ static void test_empty_context(void) {
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
it = grpc_auth_context_find_properties_by_name(ctx, "foo");
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
- grpc_auth_context_unref(ctx);
+ GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
}
static void test_simple_context(void) {
@@ -86,7 +86,7 @@ static void test_simple_context(void) {
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[1]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
- grpc_auth_context_unref(ctx);
+ GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
}
static void test_chained_context(void) {
@@ -96,7 +96,7 @@ static void test_chained_context(void) {
size_t i;
gpr_log(GPR_INFO, "test_chained_context");
- grpc_auth_context_unref(chained);
+ GRPC_AUTH_CONTEXT_UNREF(chained, "chained");
chained->properties[0] =
grpc_auth_property_init_from_cstring("name", "padapo");
chained->properties[1] = grpc_auth_property_init_from_cstring("foo", "baz");
@@ -129,7 +129,7 @@ static void test_chained_context(void) {
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &chained->properties[0]);
GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL);
- grpc_auth_context_unref(ctx);
+ GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
}
diff --git a/test/core/security/base64_test.c b/test/core/security/base64_test.c
index a922896bc3..f8b7ebf554 100644
--- a/test/core/security/base64_test.c
+++ b/test/core/security/base64_test.c
@@ -169,6 +169,43 @@ static void test_rfc4648_test_vectors(void) {
gpr_free(b64);
}
+static void test_unpadded_decode(void) {
+ gpr_slice decoded;
+
+ decoded = grpc_base64_decode("Zm9vYmFy", 0);
+ GPR_ASSERT(!GPR_SLICE_IS_EMPTY(decoded));
+ GPR_ASSERT(gpr_slice_str_cmp(decoded, "foobar") == 0);
+ gpr_slice_unref(decoded);
+
+ decoded = grpc_base64_decode("Zm9vYmE", 0);
+ GPR_ASSERT(!GPR_SLICE_IS_EMPTY(decoded));
+ GPR_ASSERT(gpr_slice_str_cmp(decoded, "fooba") == 0);
+ gpr_slice_unref(decoded);
+
+ decoded = grpc_base64_decode("Zm9vYg", 0);
+ GPR_ASSERT(!GPR_SLICE_IS_EMPTY(decoded));
+ GPR_ASSERT(gpr_slice_str_cmp(decoded, "foob") == 0);
+ gpr_slice_unref(decoded);
+
+ decoded = grpc_base64_decode("Zm9v", 0);
+ GPR_ASSERT(!GPR_SLICE_IS_EMPTY(decoded));
+ GPR_ASSERT(gpr_slice_str_cmp(decoded, "foo") == 0);
+ gpr_slice_unref(decoded);
+
+ decoded = grpc_base64_decode("Zm8", 0);
+ GPR_ASSERT(!GPR_SLICE_IS_EMPTY(decoded));
+ GPR_ASSERT(gpr_slice_str_cmp(decoded, "fo") == 0);
+ gpr_slice_unref(decoded);
+
+ decoded = grpc_base64_decode("Zg", 0);
+ GPR_ASSERT(!GPR_SLICE_IS_EMPTY(decoded));
+ GPR_ASSERT(gpr_slice_str_cmp(decoded, "f") == 0);
+ gpr_slice_unref(decoded);
+
+ decoded = grpc_base64_decode("", 0);
+ GPR_ASSERT(GPR_SLICE_IS_EMPTY(decoded));
+}
+
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_simple_encode_decode_b64_no_multiline();
@@ -181,5 +218,6 @@ int main(int argc, char **argv) {
test_full_range_encode_decode_b64_urlsafe_multiline();
test_url_safe_unsafe_mismtach_failure();
test_rfc4648_test_vectors();
+ test_unpadded_decode();
return 0;
}
diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c
index 3202df3328..767f724b62 100644
--- a/test/core/security/fetch_oauth2.c
+++ b/test/core/security/fetch_oauth2.c
@@ -46,8 +46,7 @@
#include "src/core/support/file.h"
typedef struct {
- gpr_cv cv;
- gpr_mu mu;
+ grpc_pollset pollset;
int is_done;
} synchronizer;
@@ -69,10 +68,10 @@ static void on_oauth2_response(void *user_data,
printf("Got token: %s.\n", token);
gpr_free(token);
}
- gpr_mu_lock(&sync->mu);
+ gpr_mu_lock(GRPC_POLLSET_MU(&sync->pollset));
sync->is_done = 1;
- gpr_mu_unlock(&sync->mu);
- gpr_cv_signal(&sync->cv);
+ grpc_pollset_kick(&sync->pollset);
+ gpr_mu_unlock(GRPC_POLLSET_MU(&sync->pollset));
}
static grpc_credentials *create_service_account_creds(
@@ -176,18 +175,16 @@ int main(int argc, char **argv) {
}
GPR_ASSERT(creds != NULL);
- gpr_mu_init(&sync.mu);
- gpr_cv_init(&sync.cv);
+ grpc_pollset_init(&sync.pollset);
sync.is_done = 0;
- grpc_credentials_get_request_metadata(creds, "", on_oauth2_response, &sync);
+ grpc_credentials_get_request_metadata(creds, &sync.pollset, "", on_oauth2_response, &sync);
- gpr_mu_lock(&sync.mu);
- while (!sync.is_done) gpr_cv_wait(&sync.cv, &sync.mu, gpr_inf_future);
- gpr_mu_unlock(&sync.mu);
+ gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
+ while (!sync.is_done) grpc_pollset_work(&sync.pollset, gpr_inf_future);
+ gpr_mu_unlock(GRPC_POLLSET_MU(&sync.pollset));
- gpr_mu_destroy(&sync.mu);
- gpr_cv_destroy(&sync.cv);
+ grpc_pollset_destroy(&sync.pollset);
grpc_credentials_release(creds);
gpr_cmdline_destroy(cl);
grpc_shutdown();
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index 051e8607c4..a0da5b2d93 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -44,8 +44,7 @@
#include <grpc/support/sync.h>
typedef struct {
- gpr_cv cv;
- gpr_mu mu;
+ grpc_pollset pollset;
int is_done;
} synchronizer;
@@ -61,10 +60,10 @@ static void on_metadata_response(void *user_data,
printf("\nGot token: %s\n\n",
(const char *)GPR_SLICE_START_PTR(md_elems[0].value));
}
- gpr_mu_lock(&sync->mu);
+ gpr_mu_lock(GRPC_POLLSET_MU(&sync->pollset));
sync->is_done = 1;
- gpr_mu_unlock(&sync->mu);
- gpr_cv_signal(&sync->cv);
+ grpc_pollset_kick(&sync->pollset);
+ gpr_mu_unlock(GRPC_POLLSET_MU(&sync->pollset));
}
int main(int argc, char **argv) {
@@ -86,18 +85,16 @@ int main(int argc, char **argv) {
goto end;
}
- gpr_mu_init(&sync.mu);
- gpr_cv_init(&sync.cv);
+ grpc_pollset_init(&sync.pollset);
sync.is_done = 0;
- grpc_credentials_get_request_metadata(creds, "", on_metadata_response, &sync);
+ grpc_credentials_get_request_metadata(creds, &sync.pollset, "", on_metadata_response, &sync);
- gpr_mu_lock(&sync.mu);
- while (!sync.is_done) gpr_cv_wait(&sync.cv, &sync.mu, gpr_inf_future);
- gpr_mu_unlock(&sync.mu);
+ gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
+ while (!sync.is_done) grpc_pollset_work(&sync.pollset, gpr_inf_future);
+ gpr_mu_unlock(GRPC_POLLSET_MU(&sync.pollset));
- gpr_mu_destroy(&sync.mu);
- gpr_cv_destroy(&sync.cv);
+ grpc_pollset_destroy(&sync.pollset);
grpc_credentials_release(creds);
end:
diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c
new file mode 100644
index 0000000000..b37fd7213d
--- /dev/null
+++ b/test/core/security/security_connector_test.c
@@ -0,0 +1,256 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "src/core/security/security_connector.h"
+#include "src/core/security/security_context.h"
+#include "src/core/tsi/ssl_transport_security.h"
+#include "src/core/tsi/transport_security.h"
+#include "test/core/util/test_config.h"
+
+#include <grpc/grpc_security.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+static int check_transport_security_type(const grpc_auth_context *ctx) {
+ grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
+ ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME);
+ const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it);
+ if (prop == NULL) return 0;
+ if (strncmp(prop->value, GRPC_SSL_TRANSPORT_SECURITY_TYPE,
+ prop->value_length) != 0) {
+ return 0;
+ }
+ /* Check that we have only one property with this name. */
+ if (grpc_auth_property_iterator_next(&it) != NULL) return 0;
+ return 1;
+}
+
+static void test_unauthenticated_ssl_peer(void) {
+ tsi_peer peer;
+ grpc_auth_context *ctx;
+ GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
+ &peer.properties[0]) == TSI_OK);
+ ctx = tsi_ssl_peer_to_auth_context(&peer);
+ GPR_ASSERT(ctx != NULL);
+ GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx));
+ GPR_ASSERT(check_transport_security_type(ctx));
+
+ tsi_peer_destruct(&peer);
+ GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
+}
+
+static int check_identity(const grpc_auth_context *ctx,
+ const char *expected_property_name,
+ const char **expected_identities,
+ size_t num_identities) {
+ grpc_auth_property_iterator it;
+ const grpc_auth_property *prop;
+ size_t i;
+ GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
+ it = grpc_auth_context_peer_identity(ctx);
+ for (i = 0; i < num_identities; i++) {
+ prop = grpc_auth_property_iterator_next(&it);
+ if (prop == NULL) {
+ gpr_log(GPR_ERROR, "Expected identity value %s not found.",
+ expected_identities[i]);
+ return 0;
+ }
+ if (strcmp(prop->name, expected_property_name) != 0) {
+ gpr_log(GPR_ERROR, "Expected peer identity property name %s and got %s.",
+ expected_property_name, prop->name);
+ return 0;
+ }
+ if (strncmp(prop->value, expected_identities[i], prop->value_length) != 0) {
+ gpr_log(GPR_ERROR, "Expected peer identity %s and got %s.",
+ expected_identities[i], prop->value);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int check_x509_cn(const grpc_auth_context *ctx,
+ const char *expected_cn) {
+ grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
+ ctx, GRPC_X509_CN_PROPERTY_NAME);
+ const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it);
+ if (prop == NULL) {
+ gpr_log(GPR_ERROR, "CN property not found.");
+ return 0;
+ }
+ if (strncmp(prop->value, expected_cn, prop->value_length) != 0) {
+ gpr_log(GPR_ERROR, "Expected CN %s and got %s", expected_cn, prop->value);
+ return 0;
+ }
+ if (grpc_auth_property_iterator_next(&it) != NULL) {
+ gpr_log(GPR_ERROR, "Expected only one property for CN.");
+ return 0;
+ }
+ return 1;
+}
+
+static void test_cn_only_ssl_peer_to_auth_context(void) {
+ tsi_peer peer;
+ grpc_auth_context *ctx;
+ const char *expected_cn = "cn1";
+ GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
+ &peer.properties[0]) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
+ &peer.properties[1]) == TSI_OK);
+ ctx = tsi_ssl_peer_to_auth_context(&peer);
+ GPR_ASSERT(ctx != NULL);
+ GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
+ GPR_ASSERT(check_identity(ctx, GRPC_X509_CN_PROPERTY_NAME, &expected_cn, 1));
+ GPR_ASSERT(check_transport_security_type(ctx));
+ GPR_ASSERT(check_x509_cn(ctx, expected_cn));
+
+ tsi_peer_destruct(&peer);
+ GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
+}
+
+static void test_cn_and_one_san_ssl_peer_to_auth_context(void) {
+ tsi_peer peer;
+ grpc_auth_context *ctx;
+ const char *expected_cn = "cn1";
+ const char *expected_san = "san1";
+ GPR_ASSERT(tsi_construct_peer(3, &peer) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
+ &peer.properties[0]) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
+ &peer.properties[1]) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, expected_san,
+ &peer.properties[2]) == TSI_OK);
+ ctx = tsi_ssl_peer_to_auth_context(&peer);
+ GPR_ASSERT(ctx != NULL);
+ GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
+ GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, &expected_san, 1));
+ GPR_ASSERT(check_transport_security_type(ctx));
+ GPR_ASSERT(check_x509_cn(ctx, expected_cn));
+
+ tsi_peer_destruct(&peer);
+ GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
+}
+
+static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) {
+ tsi_peer peer;
+ grpc_auth_context *ctx;
+ const char *expected_cn = "cn1";
+ const char *expected_sans[] = {"san1", "san2", "san3"};
+ size_t i;
+ GPR_ASSERT(tsi_construct_peer(2 + GPR_ARRAY_SIZE(expected_sans), &peer) ==
+ TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
+ &peer.properties[0]) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
+ &peer.properties[1]) == TSI_OK);
+ for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) {
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
+ expected_sans[i], &peer.properties[2 + i]) == TSI_OK);
+ }
+ ctx = tsi_ssl_peer_to_auth_context(&peer);
+ GPR_ASSERT(ctx != NULL);
+ GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
+ GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans,
+ GPR_ARRAY_SIZE(expected_sans)));
+ GPR_ASSERT(check_transport_security_type(ctx));
+ GPR_ASSERT(check_x509_cn(ctx, expected_cn));
+
+ tsi_peer_destruct(&peer);
+ GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
+}
+
+static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(
+ void) {
+ tsi_peer peer;
+ grpc_auth_context *ctx;
+ const char *expected_cn = "cn1";
+ const char *expected_sans[] = {"san1", "san2", "san3"};
+ size_t i;
+ GPR_ASSERT(tsi_construct_peer(4 + GPR_ARRAY_SIZE(expected_sans), &peer) ==
+ TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
+ &peer.properties[0]) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ "foo", "bar", &peer.properties[1]) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
+ &peer.properties[2]) == TSI_OK);
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ "chapi", "chapo", &peer.properties[3]) == TSI_OK);
+ for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) {
+ GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+ TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
+ expected_sans[i], &peer.properties[4 + i]) == TSI_OK);
+ }
+ ctx = tsi_ssl_peer_to_auth_context(&peer);
+ GPR_ASSERT(ctx != NULL);
+ GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
+ GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans,
+ GPR_ARRAY_SIZE(expected_sans)));
+ GPR_ASSERT(check_transport_security_type(ctx));
+ GPR_ASSERT(check_x509_cn(ctx, expected_cn));
+
+ tsi_peer_destruct(&peer);
+ GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
+}
+
+int main(int argc, char **argv) {
+ grpc_test_init(argc, argv);
+ grpc_init();
+
+ test_unauthenticated_ssl_peer();
+ test_cn_only_ssl_peer_to_auth_context();
+ test_cn_and_one_san_ssl_peer_to_auth_context();
+ test_cn_and_multiple_sans_ssl_peer_to_auth_context();
+ test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context();
+
+ grpc_shutdown();
+ return 0;
+}
diff --git a/test/core/surface/byte_buffer_reader_test.c b/test/core/surface/byte_buffer_reader_test.c
index 7c2cb9484a..d9c60e4212 100644
--- a/test/core/surface/byte_buffer_reader_test.c
+++ b/test/core/surface/byte_buffer_reader_test.c
@@ -160,6 +160,30 @@ static void test_read_deflate_compressed_slice(void) {
read_compressed_slice(GRPC_COMPRESS_DEFLATE, INPUT_SIZE);
}
+static void test_byte_buffer_from_reader(void) {
+ gpr_slice slice;
+ grpc_byte_buffer *buffer, *buffer_from_reader;
+ grpc_byte_buffer_reader reader;
+
+ LOG_TEST("test_byte_buffer_from_reader");
+ slice = gpr_slice_malloc(4);
+ memcpy(GPR_SLICE_START_PTR(slice), "test", 4);
+ buffer = grpc_raw_byte_buffer_create(&slice, 1);
+ gpr_slice_unref(slice);
+ grpc_byte_buffer_reader_init(&reader, buffer);
+
+ buffer_from_reader = grpc_raw_byte_buffer_from_reader(&reader);
+ GPR_ASSERT(buffer->type == buffer_from_reader->type);
+ GPR_ASSERT(buffer_from_reader->data.raw.compression == GRPC_COMPRESS_NONE);
+ GPR_ASSERT(buffer_from_reader->data.raw.slice_buffer.count == 1);
+ GPR_ASSERT(memcmp(GPR_SLICE_START_PTR(
+ buffer_from_reader->data.raw.slice_buffer.slices[0]),
+ "test", 4) == 0);
+
+ grpc_byte_buffer_destroy(buffer);
+ grpc_byte_buffer_destroy(buffer_from_reader);
+}
+
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_read_one_slice();
@@ -167,6 +191,7 @@ int main(int argc, char **argv) {
test_read_none_compressed_slice();
test_read_gzip_compressed_slice();
test_read_deflate_compressed_slice();
+ test_byte_buffer_from_reader();
return 0;
}
diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc
index 7876e8dee3..645226f375 100644
--- a/test/cpp/end2end/client_crash_test.cc
+++ b/test/cpp/end2end/client_crash_test.cc
@@ -140,7 +140,8 @@ TEST_F(CrashTest, KillAfterWrite) {
KillServer();
- EXPECT_FALSE(stream->Read(&response));
+ // This may succeed or fail depending on how quick the server was
+ stream->Read(&response);
EXPECT_FALSE(stream->Finish().ok());
}
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 45ba8b0878..5e850ea30a 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -68,6 +68,8 @@ namespace testing {
namespace {
+const char* kServerCancelAfterReads = "cancel_after_reads";
+
// When echo_deadline is requested, deadline seen in the ServerContext is set in
// the response in seconds.
void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request,
@@ -131,7 +133,23 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
EchoResponse* response) GRPC_OVERRIDE {
EchoRequest request;
response->set_message("");
+ int cancel_after_reads = 0;
+ const std::multimap<grpc::string, grpc::string> client_initial_metadata =
+ context->client_metadata();
+ if (client_initial_metadata.find(kServerCancelAfterReads) !=
+ client_initial_metadata.end()) {
+ std::istringstream iss(
+ client_initial_metadata.find(kServerCancelAfterReads)->second);
+ iss >> cancel_after_reads;
+ gpr_log(GPR_INFO, "cancel_after_reads %d", cancel_after_reads);
+ }
while (reader->Read(&request)) {
+ if (cancel_after_reads == 1) {
+ gpr_log(GPR_INFO, "return cancel status");
+ return Status::CANCELLED;
+ } else if (cancel_after_reads > 0) {
+ cancel_after_reads--;
+ }
response->mutable_message()->append(request.message());
}
return Status::OK;
@@ -687,6 +705,27 @@ TEST_F(End2endTest, OverridePerCallCredentials) {
EXPECT_TRUE(s.ok());
}
+// Client sends 20 requests and the server returns CANCELLED status after
+// reading 10 requests.
+TEST_F(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);
+}
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index 7132b6b1f1..b9d47b32de 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -33,10 +33,10 @@
#include <memory>
-#include "src/cpp/proto/proto_utils.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo.grpc.pb.h"
+#include <grpc++/impl/proto_utils.h>
#include <grpc++/async_generic_service.h>
#include <grpc++/async_unary_call.h>
#include <grpc++/byte_buffer.h>
diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc
index 1b7a8d26b2..8c8d927d15 100644
--- a/test/cpp/qps/client_async.cc
+++ b/test/cpp/qps/client_async.cc
@@ -168,7 +168,7 @@ class AsyncClient : public Client {
if (!closed_loop_) {
rpc_deadlines_.emplace_back();
next_channel_.push_back(i % channel_count_);
- issue_allowed_.push_back(true);
+ issue_allowed_.emplace_back(true);
grpc_time next_issue;
NextIssueTime(i, &next_issue);
@@ -234,12 +234,6 @@ class AsyncClient : public Client {
GPR_ASSERT(false);
break;
}
- if ((closed_loop_ || !rpc_deadlines_[thread_idx].empty()) &&
- grpc_time_source::now() > deadline) {
- // we have missed some 1-second deadline, which is worth noting
- gpr_log(GPR_INFO, "Missed an RPC deadline");
- // Don't give up, as there might be some truly heavy tails
- }
if (got_event) {
ClientRpcContext* ctx = ClientRpcContext::detag(got_tag);
if (ctx->RunNextState(ok, histogram) == false) {
@@ -313,11 +307,20 @@ class AsyncClient : public Client {
}
private:
+ class boolean { // exists only to avoid data-race on vector<bool>
+ public:
+ boolean(): val_(false) {}
+ boolean(bool b): val_(b) {}
+ operator bool() const {return val_;}
+ boolean& operator=(bool b) {val_=b; return *this;}
+ private:
+ bool val_;
+ };
std::vector<std::unique_ptr<CompletionQueue>> cli_cqs_;
std::vector<deadline_list> rpc_deadlines_; // per thread deadlines
std::vector<int> next_channel_; // per thread round-robin channel ctr
- std::vector<bool> issue_allowed_; // may this thread attempt to issue
+ std::vector<boolean> issue_allowed_; // may this thread attempt to issue
std::vector<grpc_time> next_issue_; // when should it issue?
std::vector<std::mutex> channel_lock_;
diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc
index 423275ee85..f1cea5ee66 100644
--- a/test/cpp/qps/qps_worker.cc
+++ b/test/cpp/qps/qps_worker.cc
@@ -31,7 +31,7 @@
*
*/
-#include "qps_worker.h"
+#include "test/cpp/qps/qps_worker.h"
#include <cassert>
#include <memory>
diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc
index 678ea080d1..94aacdbd1c 100644
--- a/test/cpp/qps/report.cc
+++ b/test/cpp/qps/report.cc
@@ -43,39 +43,39 @@ void CompositeReporter::add(std::unique_ptr<Reporter> reporter) {
reporters_.emplace_back(std::move(reporter));
}
-void CompositeReporter::ReportQPS(const ScenarioResult& result) const {
+void CompositeReporter::ReportQPS(const ScenarioResult& result) {
for (size_t i = 0; i < reporters_.size(); ++i) {
reporters_[i]->ReportQPS(result);
}
}
-void CompositeReporter::ReportQPSPerCore(const ScenarioResult& result) const {
+void CompositeReporter::ReportQPSPerCore(const ScenarioResult& result) {
for (size_t i = 0; i < reporters_.size(); ++i) {
reporters_[i]->ReportQPSPerCore(result);
}
}
-void CompositeReporter::ReportLatency(const ScenarioResult& result) const {
+void CompositeReporter::ReportLatency(const ScenarioResult& result) {
for (size_t i = 0; i < reporters_.size(); ++i) {
reporters_[i]->ReportLatency(result);
}
}
-void CompositeReporter::ReportTimes(const ScenarioResult& result) const {
+void CompositeReporter::ReportTimes(const ScenarioResult& result) {
for (size_t i = 0; i < reporters_.size(); ++i) {
reporters_[i]->ReportTimes(result);
}
}
-void GprLogReporter::ReportQPS(const ScenarioResult& result) const {
+void GprLogReporter::ReportQPS(const ScenarioResult& result) {
gpr_log(GPR_INFO, "QPS: %.1f",
result.latencies.Count() /
average(result.client_resources,
[](ResourceUsage u) { return u.wall_time; }));
}
-void GprLogReporter::ReportQPSPerCore(const ScenarioResult& result) const {
+void GprLogReporter::ReportQPSPerCore(const ScenarioResult& result) {
auto qps =
result.latencies.Count() /
average(result.client_resources,
@@ -85,7 +85,7 @@ void GprLogReporter::ReportQPSPerCore(const ScenarioResult& result) const {
qps / result.server_config.threads());
}
-void GprLogReporter::ReportLatency(const ScenarioResult& result) const {
+void GprLogReporter::ReportLatency(const ScenarioResult& result) {
gpr_log(GPR_INFO,
"Latencies (50/90/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f/%.1f us",
result.latencies.Percentile(50) / 1000,
@@ -95,7 +95,7 @@ void GprLogReporter::ReportLatency(const ScenarioResult& result) const {
result.latencies.Percentile(99.9) / 1000);
}
-void GprLogReporter::ReportTimes(const ScenarioResult& result) const {
+void GprLogReporter::ReportTimes(const ScenarioResult& result) {
gpr_log(GPR_INFO, "Server system time: %.2f%%",
100.0 * sum(result.server_resources,
[](ResourceUsage u) { return u.system_time; }) /
diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h
index 0cce08816a..b1cf83fc23 100644
--- a/test/cpp/qps/report.h
+++ b/test/cpp/qps/report.h
@@ -59,16 +59,16 @@ class Reporter {
string name() const { return name_; }
/** Reports QPS for the given \a result. */
- virtual void ReportQPS(const ScenarioResult& result) const = 0;
+ virtual void ReportQPS(const ScenarioResult& result) = 0;
/** Reports QPS per core as (YYY/server core). */
- virtual void ReportQPSPerCore(const ScenarioResult& result) const = 0;
+ virtual void ReportQPSPerCore(const ScenarioResult& result) = 0;
/** Reports latencies for the 50, 90, 95, 99 and 99.9 percentiles, in ms. */
- virtual void ReportLatency(const ScenarioResult& result) const = 0;
+ virtual void ReportLatency(const ScenarioResult& result) = 0;
/** Reports system and user time for client and server systems. */
- virtual void ReportTimes(const ScenarioResult& result) const = 0;
+ virtual void ReportTimes(const ScenarioResult& result) = 0;
private:
const string name_;
@@ -82,10 +82,10 @@ class CompositeReporter : public Reporter {
/** Adds a \a reporter to the composite. */
void add(std::unique_ptr<Reporter> reporter);
- void ReportQPS(const ScenarioResult& result) const GRPC_OVERRIDE;
- void ReportQPSPerCore(const ScenarioResult& result) const GRPC_OVERRIDE;
- void ReportLatency(const ScenarioResult& result) const GRPC_OVERRIDE;
- void ReportTimes(const ScenarioResult& result) const GRPC_OVERRIDE;
+ void ReportQPS(const ScenarioResult& result) GRPC_OVERRIDE;
+ void ReportQPSPerCore(const ScenarioResult& result) GRPC_OVERRIDE;
+ void ReportLatency(const ScenarioResult& result) GRPC_OVERRIDE;
+ void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE;
private:
std::vector<std::unique_ptr<Reporter> > reporters_;
@@ -97,10 +97,10 @@ class GprLogReporter : public Reporter {
GprLogReporter(const string& name) : Reporter(name) {}
private:
- void ReportQPS(const ScenarioResult& result) const GRPC_OVERRIDE;
- void ReportQPSPerCore(const ScenarioResult& result) const GRPC_OVERRIDE;
- void ReportLatency(const ScenarioResult& result) const GRPC_OVERRIDE;
- void ReportTimes(const ScenarioResult& result) const GRPC_OVERRIDE;
+ void ReportQPS(const ScenarioResult& result) GRPC_OVERRIDE;
+ void ReportQPSPerCore(const ScenarioResult& result) GRPC_OVERRIDE;
+ void ReportLatency(const ScenarioResult& result) GRPC_OVERRIDE;
+ void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE;
};
} // namespace testing
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 210aef4fd6..f5251e961b 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -64,7 +64,7 @@ namespace testing {
class AsyncQpsServerTest : public Server {
public:
- AsyncQpsServerTest(const ServerConfig &config, int port) : shutdown_(false) {
+ AsyncQpsServerTest(const ServerConfig &config, int port) {
char *server_address = NULL;
gpr_join_host_port(&server_address, "::", port);
@@ -97,6 +97,9 @@ class AsyncQpsServerTest : public Server {
}
}
for (int i = 0; i < config.threads(); i++) {
+ shutdown_state_.emplace_back(new PerThreadShutdownState());
+ }
+ for (int i = 0; i < config.threads(); i++) {
threads_.push_back(std::thread([=]() {
// Wait until work is available or we are shutting down
bool ok;
@@ -105,11 +108,9 @@ class AsyncQpsServerTest : public Server {
ServerRpcContext *ctx = detag(got_tag);
// The tag is a pointer to an RPC context to invoke
bool still_going = ctx->RunNextState(ok);
- std::unique_lock<std::mutex> g(shutdown_mutex_);
- if (!shutdown_) {
+ if (!shutdown_state_[i]->shutdown()) {
// this RPC context is done, so refresh it
if (!still_going) {
- g.unlock();
ctx->Reset();
}
} else {
@@ -122,9 +123,8 @@ class AsyncQpsServerTest : public Server {
}
~AsyncQpsServerTest() {
server_->Shutdown();
- {
- std::lock_guard<std::mutex> g(shutdown_mutex_);
- shutdown_ = true;
+ for (auto ss = shutdown_state_.begin(); ss != shutdown_state_.end(); ++ss) {
+ (*ss)->set_shutdown();
}
for (auto thr = threads_.begin(); thr != threads_.end(); thr++) {
thr->join();
@@ -316,8 +316,25 @@ class AsyncQpsServerTest : public Server {
TestService::AsyncService async_service_;
std::forward_list<ServerRpcContext *> contexts_;
- std::mutex shutdown_mutex_;
- bool shutdown_;
+ class PerThreadShutdownState {
+ public:
+ PerThreadShutdownState() : shutdown_(false) {}
+
+ bool shutdown() const {
+ std::lock_guard<std::mutex> lock(mutex_);
+ return shutdown_;
+ }
+
+ void set_shutdown() {
+ std::lock_guard<std::mutex> lock(mutex_);
+ shutdown_ = true;
+ }
+
+ private:
+ mutable std::mutex mutex_;
+ bool shutdown_;
+ };
+ std::vector<std::unique_ptr<PerThreadShutdownState>> shutdown_state_;
};
std::unique_ptr<Server> CreateAsyncServer(const ServerConfig &config,
diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc
index dfc102fc17..14a8b0b089 100644
--- a/test/cpp/qps/worker.cc
+++ b/test/cpp/qps/worker.cc
@@ -40,7 +40,7 @@
#include <grpc/support/time.h>
#include <gflags/gflags.h>
-#include "qps_worker.h"
+#include "test/cpp/qps/qps_worker.h"
#include "test/cpp/util/test_config.h"
DEFINE_int32(driver_port, 0, "Driver server port.");
diff --git a/test/cpp/util/byte_buffer_test.cc b/test/cpp/util/byte_buffer_test.cc
new file mode 100644
index 0000000000..13eb49730a
--- /dev/null
+++ b/test/cpp/util/byte_buffer_test.cc
@@ -0,0 +1,115 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc++/byte_buffer.h>
+
+#include <cstring>
+#include <vector>
+
+#include <grpc/support/slice.h>
+#include <grpc++/slice.h>
+#include <gtest/gtest.h>
+
+namespace grpc {
+namespace {
+
+const char* kContent1 = "hello xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+const char* kContent2 = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy world";
+
+class ByteBufferTest : public ::testing::Test {
+};
+
+TEST_F(ByteBufferTest, CreateFromSingleSlice) {
+ gpr_slice hello = gpr_slice_from_copied_string(kContent1);
+ Slice s(hello, Slice::STEAL_REF);
+ ByteBuffer buffer(&s, 1);
+}
+
+TEST_F(ByteBufferTest, CreateFromVector) {
+ gpr_slice hello = gpr_slice_from_copied_string(kContent1);
+ gpr_slice world = gpr_slice_from_copied_string(kContent2);
+ std::vector<Slice> slices;
+ slices.push_back(Slice(hello, Slice::STEAL_REF));
+ slices.push_back(Slice(world, Slice::STEAL_REF));
+ ByteBuffer buffer(&slices[0], 2);
+}
+
+TEST_F(ByteBufferTest, Clear) {
+ gpr_slice hello = gpr_slice_from_copied_string(kContent1);
+ Slice s(hello, Slice::STEAL_REF);
+ ByteBuffer buffer(&s, 1);
+ buffer.Clear();
+}
+
+TEST_F(ByteBufferTest, Length) {
+ gpr_slice hello = gpr_slice_from_copied_string(kContent1);
+ gpr_slice world = gpr_slice_from_copied_string(kContent2);
+ std::vector<Slice> slices;
+ slices.push_back(Slice(hello, Slice::STEAL_REF));
+ slices.push_back(Slice(world, Slice::STEAL_REF));
+ ByteBuffer buffer(&slices[0], 2);
+ EXPECT_EQ(strlen(kContent1) + strlen(kContent2), buffer.Length());
+}
+
+bool SliceEqual(const Slice& a, gpr_slice b) {
+ if (a.size() != GPR_SLICE_LENGTH(b)) {
+ return false;
+ }
+ for (size_t i = 0; i < a.size(); i++) {
+ if (a.begin()[i] != GPR_SLICE_START_PTR(b)[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+TEST_F(ByteBufferTest, Dump) {
+ gpr_slice hello = gpr_slice_from_copied_string(kContent1);
+ gpr_slice world = gpr_slice_from_copied_string(kContent2);
+ std::vector<Slice> slices;
+ slices.push_back(Slice(hello, Slice::STEAL_REF));
+ slices.push_back(Slice(world, Slice::STEAL_REF));
+ ByteBuffer buffer(&slices[0], 2);
+ slices.clear();
+ buffer.Dump(&slices);
+ EXPECT_TRUE(SliceEqual(slices[0], hello));
+ EXPECT_TRUE(SliceEqual(slices[1], world));
+}
+
+} // namespace
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index 32d61b0307..3c3baeb769 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -88,7 +88,7 @@ void ParseMetadataFlag(
return;
}
std::vector<grpc::string> fields;
- grpc::string delim(":");
+ const char* delim = ":";
size_t cur, next = -1;
do {
cur = next + 1;
diff --git a/test/cpp/util/slice_test.cc b/test/cpp/util/slice_test.cc
new file mode 100644
index 0000000000..eb328490e1
--- /dev/null
+++ b/test/cpp/util/slice_test.cc
@@ -0,0 +1,77 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc++/slice.h>
+
+#include <grpc/support/slice.h>
+#include <gtest/gtest.h>
+
+namespace grpc {
+namespace {
+
+const char* kContent = "hello xxxxxxxxxxxxxxxxxxxx world";
+
+class SliceTest : public ::testing::Test {
+ protected:
+ void CheckSlice(const Slice& s, const grpc::string& content) {
+ EXPECT_EQ(content.size(), s.size());
+ EXPECT_EQ(content,
+ grpc::string(reinterpret_cast<const char*>(s.begin()), s.size()));
+ }
+};
+
+TEST_F(SliceTest, Steal) {
+ gpr_slice s = gpr_slice_from_copied_string(kContent);
+ Slice spp(s, Slice::STEAL_REF);
+ CheckSlice(spp, kContent);
+}
+
+TEST_F(SliceTest, Add) {
+ gpr_slice s = gpr_slice_from_copied_string(kContent);
+ Slice spp(s, Slice::ADD_REF);
+ gpr_slice_unref(s);
+ CheckSlice(spp, kContent);
+}
+
+TEST_F(SliceTest, Empty) {
+ Slice empty_slice;
+ CheckSlice(empty_slice, "");
+}
+
+} // namespace
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/proto/messages.proto b/test/proto/messages.proto
index 65a8140465..500e79cc81 100644
--- a/test/proto/messages.proto
+++ b/test/proto/messages.proto
@@ -46,6 +46,14 @@ enum PayloadType {
RANDOM = 2;
}
+// Compression algorithms
+enum CompressionType {
+ // No compression
+ NONE = 0;
+ GZIP = 1;
+ DEFLATE = 2;
+}
+
// A block of data, to simply increase gRPC message size.
message Payload {
// The type of data in body.
@@ -54,6 +62,13 @@ message Payload {
optional bytes body = 2;
}
+// A protobuf representation for grpc status. This is used by test
+// clients to specify a status that the server should attempt to return.
+message EchoStatus {
+ optional int32 code = 1;
+ optional string message = 2;
+}
+
// Unary request.
message SimpleRequest {
// Desired payload type in the response from the server.
@@ -72,6 +87,12 @@ message SimpleRequest {
// Whether SimpleResponse should include OAuth scope.
optional bool fill_oauth_scope = 5;
+
+ // Compression algorithm to be used by the server for the response (stream)
+ optional CompressionType response_compression = 6;
+
+ // Whether server should return a given status
+ optional EchoStatus response_status = 7;
}
// Unary response, as configured by the request.
@@ -123,6 +144,12 @@ message StreamingOutputCallRequest {
// Optional input payload sent along with the request.
optional Payload payload = 3;
+
+ // Compression algorithm to be used by the server for the response (stream)
+ optional CompressionType response_compression = 6;
+
+ // Whether server should return a given status
+ optional EchoStatus response_status = 7;
}
// Server-streaming response, as configured by the request and parameters.
diff --git a/test/proto/test.proto b/test/proto/test.proto
index b9483d8437..1214152513 100644
--- a/test/proto/test.proto
+++ b/test/proto/test.proto
@@ -71,3 +71,11 @@ service TestService {
rpc HalfDuplexCall(stream StreamingOutputCallRequest)
returns (stream StreamingOutputCallResponse);
}
+
+
+// A simple service NOT implemented at servers so clients can test for
+// that case.
+service UnimplementedService {
+ // A call that no server should implement
+ rpc UnimplementedCall(grpc.testing.Empty) returns(grpc.testing.Empty);
+}