diff options
Diffstat (limited to 'test')
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); +} |