diff options
author | 2015-03-11 14:31:00 -0700 | |
---|---|---|
committer | 2015-03-11 14:31:00 -0700 | |
commit | f859510340d0d13fce24d9c0e69455b6bd205337 (patch) | |
tree | c1b6ad57d479a617622fc07b666750a682b6c972 /test | |
parent | 25770b02d634ba69dfef6bc2d68fbce167acfcef (diff) | |
parent | 6063b9ff526b293a389fa0377a59346c5bb222c1 (diff) |
Merge branch 'master' into jwt
Diffstat (limited to 'test')
55 files changed, 2307 insertions, 524 deletions
diff --git a/test/compiler/python_plugin_test.py b/test/compiler/python_plugin_test.py index 1981f49fbb..9cf3c624c0 100644 --- a/test/compiler/python_plugin_test.py +++ b/test/compiler/python_plugin_test.py @@ -32,12 +32,14 @@ import contextlib import errno import itertools import os +import shutil import subprocess import sys +import tempfile import time import unittest -from grpc.framework.face import exceptions +from grpc.early_adopter import exceptions from grpc.framework.foundation import future # Identifiers of entities we expect to find in the generated module. @@ -55,8 +57,8 @@ DOES_NOT_MATTER_DELAY = 0 NO_DELAY = 0 LONG_DELAY = 1 -# Assigned in __main__. -_build_mode = None +# Build mode environment variable set by tools/run_tests/run_tests.py. +_build_mode = os.environ['CONFIG'] class _ServicerMethods(object): @@ -227,24 +229,26 @@ class PythonPluginTest(unittest.TestCase): protoc_command = 'protoc' # Ensure that the output directory exists. - outdir = '../../gens/test/compiler/python' - try: - os.makedirs(outdir) - except OSError as exception: - if exception.errno != errno.EEXIST: - raise + self.outdir = tempfile.mkdtemp() # Invoke protoc with the plugin. cmd = [ protoc_command, '--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename, '-I %s' % os.path.dirname(test_proto_filename), - '--python_out=%s' % outdir, - '--python-grpc_out=%s' % outdir, + '--python_out=%s' % self.outdir, + '--python-grpc_out=%s' % self.outdir, os.path.basename(test_proto_filename), ] subprocess.call(' '.join(cmd), shell=True) - sys.path.append(outdir) + sys.path.append(self.outdir) + + def tearDown(self): + try: + shutil.rmtree(self.outdir) + except OSError as exc: + if exc.errno != errno.ENOENT: + raise # TODO(atash): Figure out which of theses tests is hanging flakily with small # probability. @@ -296,6 +300,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ExpirationError): response_future.result() + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testUnaryCallAsyncCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top request = test_pb2.SimpleRequest(response_size=13) @@ -325,6 +331,8 @@ class PythonPluginTest(unittest.TestCase): expected_response, response = check self.assertEqual(expected_response, response) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testStreamingOutputCallExpired(self): import test_pb2 # pylint: disable=g-import-not-at-top request = StreamingOutputRequest(test_pb2) @@ -335,6 +343,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ExpirationError): list(responses) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testStreamingOutputCallCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top request = StreamingOutputRequest(test_pb2) @@ -359,6 +369,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ServicerError): next(responses) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testStreamingInputCall(self): import test_pb2 # pylint: disable=g-import-not-at-top with _CreateService(test_pb2, NO_DELAY) as (servicer, stub, unused_server): @@ -426,6 +438,8 @@ class PythonPluginTest(unittest.TestCase): expected_response, response = check self.assertEqual(expected_response, response) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testFullDuplexCallExpired(self): import test_pb2 # pylint: disable=g-import-not-at-top request = FullDuplexRequest(test_pb2) @@ -436,6 +450,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ExpirationError): list(responses) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testFullDuplexCallCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top with _CreateService(test_pb2, NO_DELAY) as (servicer, stub, unused_server): @@ -459,6 +475,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ServicerError): next(responses) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testHalfDuplexCall(self): import test_pb2 # pylint: disable=g-import-not-at-top with _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) as ( @@ -502,14 +520,4 @@ class PythonPluginTest(unittest.TestCase): if __name__ == '__main__': os.chdir(os.path.dirname(sys.argv[0])) - parser = argparse.ArgumentParser( - description='Run Python compiler plugin test.') - parser.add_argument( - '--build_mode', dest='build_mode', type=str, default='dbg', - help='The build mode of the targets to test, e.g. "dbg", "opt", "asan", ' - 'etc.') - parser.add_argument('--port', dest='port', type=int, default=0) - args, remainder = parser.parse_known_args() - _build_mode = args.build_mode - sys.argv[1:] = remainder unittest.main() diff --git a/test/core/echo/server.c b/test/core/echo/server.c index bc84645a04..e888a0c877 100644 --- a/test/core/echo/server.c +++ b/test/core/echo/server.c @@ -143,8 +143,8 @@ int main(int argc, char **argv) { test_server1_cert}; grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1); - server = grpc_secure_server_create(ssl_creds, cq, &args); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr)); + server = grpc_server_create(cq, &args); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); grpc_server_credentials_release(ssl_creds); } else { server = grpc_server_create(cq, &args); diff --git a/test/core/end2end/cq_verifier.h b/test/core/end2end/cq_verifier.h index 8f1471060f..c1e25d8aa4 100644 --- a/test/core/end2end/cq_verifier.h +++ b/test/core/end2end/cq_verifier.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_END2END_CQ_VERIFIER_H__ -#define __GRPC_TEST_END2END_CQ_VERIFIER_H__ +#ifndef GRPC_TEST_CORE_END2END_CQ_VERIFIER_H +#define GRPC_TEST_CORE_END2END_CQ_VERIFIER_H #include <grpc/grpc.h> #include "test/core/util/test_config.h" @@ -76,4 +76,4 @@ void cq_expect_server_shutdown(cq_verifier *v, void *tag); int byte_buffer_eq_string(grpc_byte_buffer *byte_buffer, const char *string); int contains_metadata(grpc_metadata_array *array, const char *key, const char *value); -#endif /* __GRPC_TEST_END2END_CQ_VERIFIER_H__ */ +#endif /* GRPC_TEST_CORE_END2END_CQ_VERIFIER_H */ diff --git a/test/core/end2end/data/ssl_test_data.h b/test/core/end2end/data/ssl_test_data.h index 41248670d6..4f4b30ef21 100644 --- a/test/core/end2end/data/ssl_test_data.h +++ b/test/core/end2end/data/ssl_test_data.h @@ -31,11 +31,11 @@ * */ -#ifndef __GRPC_TEST_END2END_DATA_SSL_TEST_DATA_H__ -#define __GRPC_TEST_END2END_DATA_SSL_TEST_DATA_H__ +#ifndef GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H +#define GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H extern const char test_root_cert[]; extern const char test_server1_cert[]; extern const char test_server1_key[]; -#endif /* __GRPC_TEST_END2END_DATA_SSL_TEST_DATA_H__ */ +#endif /* GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H */ diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h index 8f2cd0f2e0..41c6e2ee0c 100644 --- a/test/core/end2end/end2end_tests.h +++ b/test/core/end2end/end2end_tests.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_END2END_END2END_TESTS_H__ -#define __GRPC_TEST_END2END_END2END_TESTS_H__ +#ifndef GRPC_TEST_CORE_END2END_END2END_TESTS_H +#define GRPC_TEST_CORE_END2END_END2END_TESTS_H #include <grpc/grpc.h> @@ -40,6 +40,7 @@ typedef struct grpc_end2end_test_fixture grpc_end2end_test_fixture; typedef struct grpc_end2end_test_config grpc_end2end_test_config; #define FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION 1 +#define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION 2 struct grpc_end2end_test_fixture { grpc_completion_queue *server_cq; @@ -63,4 +64,4 @@ struct grpc_end2end_test_config { void grpc_end2end_tests(grpc_end2end_test_config config); -#endif /* __GRPC_TEST_END2END_END2END_TESTS_H__ */ +#endif /* GRPC_TEST_CORE_END2END_END2END_TESTS_H */ diff --git a/test/core/end2end/fixtures/chttp2_fake_security.c b/test/core/end2end/fixtures/chttp2_fake_security.c index 247d1fd322..047d482be3 100644 --- a/test/core/end2end/fixtures/chttp2_fake_security.c +++ b/test/core/end2end/fixtures/chttp2_fake_security.c @@ -84,9 +84,9 @@ static void chttp2_init_server_secure_fullstack( grpc_server_destroy(f->server); } f->server = - grpc_secure_server_create(server_creds, f->server_cq, server_args); + grpc_server_create(f->server_cq, server_args); + GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, server_creds)); grpc_server_credentials_release(server_creds); - GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr)); grpc_server_start(f->server); } diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c index 16946d5f97..16433f5f87 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c @@ -87,9 +87,9 @@ static void chttp2_init_server_secure_fullstack( grpc_server_destroy(f->server); } f->server = - grpc_secure_server_create(server_creds, f->server_cq, server_args); + grpc_server_create(f->server_cq, server_args); + GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, server_creds)); grpc_server_credentials_release(server_creds); - GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr)); grpc_server_start(f->server); } @@ -123,7 +123,9 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( /* All test configurations */ static grpc_end2end_test_config configs[] = { - {"chttp2/simple_ssl_fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, + {"chttp2/simple_ssl_fullstack", + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION, chttp2_create_fixture_secure_fullstack, chttp2_init_client_simple_ssl_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack, diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c index c451e01024..99031df8e5 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c @@ -85,9 +85,9 @@ static void chttp2_init_server_secure_fullstack( grpc_server_destroy(f->server); } f->server = - grpc_secure_server_create(server_creds, f->server_cq, server_args); + grpc_server_create(f->server_cq, server_args); + GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, server_creds)); grpc_server_credentials_release(server_creds); - GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr)); grpc_server_start(f->server); } @@ -129,7 +129,8 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( static grpc_end2end_test_config configs[] = { {"chttp2/simple_ssl_with_oauth2_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION, chttp2_create_fixture_secure_fullstack, chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack, diff --git a/test/core/end2end/gen_build_json.py b/test/core/end2end/gen_build_json.py index 4e297b30be..67fc0a6e53 100755 --- a/test/core/end2end/gen_build_json.py +++ b/test/core/end2end/gen_build_json.py @@ -46,6 +46,7 @@ END2END_FIXTURES = [ END2END_TESTS = [ + 'bad_hostname', 'cancel_after_accept', 'cancel_after_accept_and_writes_closed', 'cancel_after_invoke', @@ -106,7 +107,7 @@ def main(): 'name': 'end2end_fixture_%s' % f, 'build': 'private', 'language': 'c', - 'secure': True, + 'secure': 'check', 'src': ['test/core/end2end/fixtures/%s.c' % f] } for f in END2END_FIXTURES] + [ @@ -114,7 +115,7 @@ def main(): 'name': 'end2end_test_%s' % t, 'build': 'private', 'language': 'c', - 'secure': False, + 'secure': 'no', 'src': ['test/core/end2end/tests/%s.c' % t], 'headers': ['test/core/end2end/tests/cancel_test_helpers.h'] } diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c index d953552c0a..ffc651ab05 100644 --- a/test/core/end2end/no_server_test.c +++ b/test/core/end2end/no_server_test.c @@ -41,7 +41,7 @@ static void *tag(gpr_intptr i) { return (void *)i; } int main(int argc, char **argv) { grpc_channel *chan; grpc_call *call; - gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5); + gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2); grpc_completion_queue *cq; cq_verifier *cqv; grpc_event *ev; diff --git a/test/core/end2end/tests/bad_hostname.c b/test/core/end2end/tests/bad_hostname.c new file mode 100644 index 0000000000..80922f3b6f --- /dev/null +++ b/test/core/end2end/tests/bad_hostname.c @@ -0,0 +1,176 @@ +/* + * + * 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 "test/core/end2end/end2end_tests.h" + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "src/core/support/string.h" +#include <grpc/byte_buffer.h> +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> +#include "test/core/end2end/cq_verifier.h" + +enum { TIMEOUT = 200000 }; + +static void *tag(gpr_intptr t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "%s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_client(&f, client_args); + config.init_server(&f, server_args); + return f; +} + +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event *ev; + grpc_completion_type type; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time()); + GPR_ASSERT(ev); + type = ev->type; + grpc_event_finish(ev); + } while (type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown(f->server); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->server_cq); + drain_cq(f->server_cq); + grpc_completion_queue_destroy(f->server_cq); + grpc_completion_queue_shutdown(f->client_cq); + drain_cq(f->client_cq); + grpc_completion_queue_destroy(f->client_cq); +} + +static void simple_request_body(grpc_end2end_test_fixture f) { + grpc_call *c; + gpr_timespec deadline = five_seconds_time(); + cq_verifier *v_client = cq_verifier_create(f.client_cq); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_call_details call_details; + grpc_status_code status; + char *details = NULL; + size_t details_capacity = 0; + + c = grpc_channel_create_call(f.client, f.client_cq, "/foo", + "slartibartfast.local", deadline); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->data.recv_status_on_client.status_details_capacity = &details_capacity; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1))); + + cq_expect_completion(v_client, tag(1), GRPC_OP_OK); + cq_verify(v_client); + + GPR_ASSERT(status == GRPC_STATUS_UNAUTHENTICATED); + + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_destroy(c); + + cq_verifier_destroy(v_client); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, __FUNCTION__, NULL, NULL); + simple_request_body(f); + end_test(&f); + config.tear_down_data(&f); +} + +void grpc_end2end_tests(grpc_end2end_test_config config) { + if (config.feature_mask & FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION) { + test_invoke_simple_request(config); + } +} diff --git a/test/core/end2end/tests/cancel_test_helpers.h b/test/core/end2end/tests/cancel_test_helpers.h index 3dd7437353..f2581dc32f 100644 --- a/test/core/end2end/tests/cancel_test_helpers.h +++ b/test/core/end2end/tests/cancel_test_helpers.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_END2END_TESTS_CANCEL_TEST_HELPERS_H__ -#define __GRPC_TEST_END2END_TESTS_CANCEL_TEST_HELPERS_H__ +#ifndef GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H +#define GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H typedef struct { grpc_call_error (*initiate_cancel)(grpc_call *call); @@ -48,4 +48,4 @@ static const cancellation_mode cancellation_modes[] = { {grpc_call_cancel, GRPC_STATUS_CANCELLED, ""}, {wait_for_deadline, GRPC_STATUS_DEADLINE_EXCEEDED, "Deadline Exceeded"}, }; -#endif +#endif /* GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H */ diff --git a/test/core/fling/server.c b/test/core/fling/server.c index 59c303015a..ca39cd84b1 100644 --- a/test/core/fling/server.c +++ b/test/core/fling/server.c @@ -205,8 +205,8 @@ int main(int argc, char **argv) { test_server1_cert}; grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1); - server = grpc_secure_server_create(ssl_creds, cq, NULL); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr)); + server = grpc_server_create(cq, NULL); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); grpc_server_credentials_release(ssl_creds); } else { server = grpc_server_create(cq, NULL); @@ -275,7 +275,7 @@ int main(int argc, char **argv) { case FLING_SERVER_SEND_STATUS_FOR_STREAMING: /* Send status and close completed at server */ grpc_call_destroy(call); - request_call(); + if (!shutdown_started) request_call(); break; case FLING_SERVER_READ_FOR_UNARY: /* Finished payload read for unary. Start all reamaining @@ -288,7 +288,7 @@ int main(int argc, char **argv) { grpc_byte_buffer_destroy(payload_buffer); payload_buffer = NULL; grpc_call_destroy(call); - request_call(); + if (!shutdown_started) request_call(); break; } break; diff --git a/test/core/iomgr/endpoint_tests.h b/test/core/iomgr/endpoint_tests.h index 3be377c4e3..1679d7bd4f 100644 --- a/test/core/iomgr/endpoint_tests.h +++ b/test/core/iomgr/endpoint_tests.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_IOMGR_ENDPOINT_TESTS_H__ -#define __GRPC_TEST_IOMGR_ENDPOINT_TESTS_H__ +#ifndef GRPC_TEST_CORE_IOMGR_ENDPOINT_TESTS_H +#define GRPC_TEST_CORE_IOMGR_ENDPOINT_TESTS_H #include <sys/types.h> @@ -54,4 +54,4 @@ struct grpc_endpoint_test_config { void grpc_endpoint_tests(grpc_endpoint_test_config config); -#endif /* __GRPC_TEST_IOMGR_ENDPOINT_TESTS_H__ */ +#endif /* GRPC_TEST_CORE_IOMGR_ENDPOINT_TESTS_H */ diff --git a/test/core/network_benchmarks/low_level_ping_pong.c b/test/core/network_benchmarks/low_level_ping_pong.c index f0a3e26c4e..7d74d0e078 100644 --- a/test/core/network_benchmarks/low_level_ping_pong.c +++ b/test/core/network_benchmarks/low_level_ping_pong.c @@ -81,7 +81,7 @@ typedef struct thread_args { /* Basic call to read() */ static int read_bytes(int fd, char *buf, size_t read_size, int spin) { - int bytes_read = 0; + size_t bytes_read = 0; int err; do { err = read(fd, buf + bytes_read, read_size - bytes_read); @@ -198,7 +198,7 @@ static int epoll_read_bytes_spin(struct thread_args *args, char *buf) { writes go directly out to the kernel. */ static int blocking_write_bytes(struct thread_args *args, char *buf) { - int bytes_written = 0; + size_t bytes_written = 0; int err; size_t write_size = args->msg_size; do { @@ -586,10 +586,10 @@ static int run_benchmark(char *socket_type, thread_args *client_args, static int run_all_benchmarks(int msg_size) { int error = 0; - int i; + size_t i; for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) { test_strategy *test_strategy = &test_strategies[i]; - int j; + size_t j; for (j = 0; j < GPR_ARRAY_SIZE(socket_types); ++j) { thread_args *client_args = malloc(sizeof(thread_args)); thread_args *server_args = malloc(sizeof(thread_args)); @@ -620,7 +620,7 @@ int main(int argc, char **argv) { int msg_size = -1; char *read_strategy = NULL; char *socket_type = NULL; - int i; + size_t i; const test_strategy *test_strategy = NULL; int error = 0; @@ -654,7 +654,7 @@ int main(int argc, char **argv) { } for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) { - if (!strcmp(test_strategies[i].name, read_strategy)) { + if (strcmp(test_strategies[i].name, read_strategy) == 0) { test_strategy = &test_strategies[i]; } } diff --git a/test/core/security/base64_test.c b/test/core/security/base64_test.c index bfd5c48777..a922896bc3 100644 --- a/test/core/security/base64_test.c +++ b/test/core/security/base64_test.c @@ -58,8 +58,8 @@ static void test_simple_encode_decode_b64(int url_safe, int multiline) { grpc_base64_encode(hello, strlen(hello), url_safe, multiline); gpr_slice hello_slice = grpc_base64_decode(hello_b64, url_safe); GPR_ASSERT(GPR_SLICE_LENGTH(hello_slice) == strlen(hello)); - GPR_ASSERT(!strncmp((const char *)GPR_SLICE_START_PTR(hello_slice), hello, - GPR_SLICE_LENGTH(hello_slice))); + GPR_ASSERT(strncmp((const char *)GPR_SLICE_START_PTR(hello_slice), hello, + GPR_SLICE_LENGTH(hello_slice)) == 0); gpr_slice_unref(hello_slice); gpr_free(hello_b64); @@ -141,31 +141,31 @@ static void test_rfc4648_test_vectors(void) { char *b64; b64 = grpc_base64_encode("", 0, 0, 0); - GPR_ASSERT(!strcmp("", b64)); + GPR_ASSERT(strcmp("", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("f", 1, 0, 0); - GPR_ASSERT(!strcmp("Zg==", b64)); + GPR_ASSERT(strcmp("Zg==", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("fo", 2, 0, 0); - GPR_ASSERT(!strcmp("Zm8=", b64)); + GPR_ASSERT(strcmp("Zm8=", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("foo", 3, 0, 0); - GPR_ASSERT(!strcmp("Zm9v", b64)); + GPR_ASSERT(strcmp("Zm9v", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("foob", 4, 0, 0); - GPR_ASSERT(!strcmp("Zm9vYg==", b64)); + GPR_ASSERT(strcmp("Zm9vYg==", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("fooba", 5, 0, 0); - GPR_ASSERT(!strcmp("Zm9vYmE=", b64)); + GPR_ASSERT(strcmp("Zm9vYmE=", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("foobar", 6, 0, 0); - GPR_ASSERT(!strcmp("Zm9vYmFy", b64)); + GPR_ASSERT(strcmp("Zm9vYmFy", b64) == 0); gpr_free(b64); } diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 50ef2d7657..078462410a 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -143,9 +143,10 @@ static void test_oauth2_token_fetcher_creds_parsing_ok(void) { GRPC_CREDENTIALS_OK); GPR_ASSERT(token_lifetime.tv_sec == 3599); GPR_ASSERT(token_lifetime.tv_nsec == 0); - GPR_ASSERT(!strcmp(grpc_mdstr_as_c_string(token_elem->key), "Authorization")); - GPR_ASSERT(!strcmp(grpc_mdstr_as_c_string(token_elem->value), - "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_")); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(token_elem->key), + "Authorization") == 0); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(token_elem->value), + "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == 0); grpc_mdelem_unref(token_elem); grpc_mdctx_unref(ctx); } @@ -294,15 +295,16 @@ static void test_ssl_oauth2_composite_creds(void) { grpc_composite_credentials_create(ssl_creds, oauth2_creds); grpc_credentials_unref(ssl_creds); grpc_credentials_unref(oauth2_creds); - GPR_ASSERT(!strcmp(composite_creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)); + GPR_ASSERT(strcmp(composite_creds->type, + GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0); GPR_ASSERT(grpc_credentials_has_request_metadata(composite_creds)); GPR_ASSERT(!grpc_credentials_has_request_metadata_only(composite_creds)); creds_array = grpc_composite_credentials_get_credentials(composite_creds); GPR_ASSERT(creds_array->num_creds == 2); - GPR_ASSERT( - !strcmp(creds_array->creds_array[0]->type, GRPC_CREDENTIALS_TYPE_SSL)); - GPR_ASSERT( - !strcmp(creds_array->creds_array[1]->type, GRPC_CREDENTIALS_TYPE_OAUTH2)); + GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, + GRPC_CREDENTIALS_TYPE_SSL) == 0); + GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, + GRPC_CREDENTIALS_TYPE_OAUTH2) == 0); grpc_credentials_get_request_metadata(composite_creds, test_service_url, check_ssl_oauth2_composite_metadata, composite_creds); @@ -338,17 +340,18 @@ static void test_ssl_oauth2_iam_composite_creds(void) { grpc_credentials_unref(oauth2_creds); grpc_credentials_unref(aux_creds); grpc_credentials_unref(iam_creds); - GPR_ASSERT(!strcmp(composite_creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)); + GPR_ASSERT(strcmp(composite_creds->type, + GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0); GPR_ASSERT(grpc_credentials_has_request_metadata(composite_creds)); GPR_ASSERT(!grpc_credentials_has_request_metadata_only(composite_creds)); creds_array = grpc_composite_credentials_get_credentials(composite_creds); GPR_ASSERT(creds_array->num_creds == 3); - GPR_ASSERT( - !strcmp(creds_array->creds_array[0]->type, GRPC_CREDENTIALS_TYPE_SSL)); - GPR_ASSERT( - !strcmp(creds_array->creds_array[1]->type, GRPC_CREDENTIALS_TYPE_OAUTH2)); - GPR_ASSERT( - !strcmp(creds_array->creds_array[2]->type, GRPC_CREDENTIALS_TYPE_IAM)); + GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, + GRPC_CREDENTIALS_TYPE_SSL) == 0); + GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, + GRPC_CREDENTIALS_TYPE_OAUTH2) == 0); + GPR_ASSERT(strcmp(creds_array->creds_array[2]->type, + GRPC_CREDENTIALS_TYPE_IAM) == 0); grpc_credentials_get_request_metadata(composite_creds, test_service_url, check_ssl_oauth2_iam_composite_metadata, composite_creds); @@ -359,12 +362,12 @@ static void on_oauth2_creds_get_metadata_success( grpc_credentials_status status) { GPR_ASSERT(status == GRPC_CREDENTIALS_OK); GPR_ASSERT(num_md == 1); - GPR_ASSERT( - !strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), "Authorization")); - GPR_ASSERT(!strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), - "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_")); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), + "Authorization") == 0); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), + "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == 0); GPR_ASSERT(user_data != NULL); - GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); + GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); } static void on_oauth2_creds_get_metadata_failure( @@ -373,19 +376,19 @@ static void on_oauth2_creds_get_metadata_failure( GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); GPR_ASSERT(num_md == 0); GPR_ASSERT(user_data != NULL); - GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); + GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); } static void validate_compute_engine_http_request( const grpc_httpcli_request *request) { GPR_ASSERT(!request->use_ssl); - GPR_ASSERT(!strcmp(request->host, "metadata")); - GPR_ASSERT( - !strcmp(request->path, - "/computeMetadata/v1/instance/service-accounts/default/token")); + GPR_ASSERT(strcmp(request->host, "metadata") == 0); + GPR_ASSERT(strcmp(request->path, + "/computeMetadata/v1/instance/service-accounts/default/token") + == 0); GPR_ASSERT(request->hdr_count == 1); - GPR_ASSERT(!strcmp(request->hdrs[0].key, "Metadata-Flavor")); - GPR_ASSERT(!strcmp(request->hdrs[0].value, "Google")); + GPR_ASSERT(strcmp(request->hdrs[0].key, "Metadata-Flavor") == 0); + GPR_ASSERT(strcmp(request->hdrs[0].value, "Google") == 0); } static int compute_engine_httpcli_get_success_override( @@ -467,19 +470,19 @@ static void validate_jwt_encode_and_sign_params( GPR_ASSERT(json_key->private_key != NULL); GPR_ASSERT(RSA_check_key(json_key->private_key)); GPR_ASSERT(json_key->type != NULL && - !(strcmp(json_key->type, "service_account"))); + strcmp(json_key->type, "service_account") == 0); GPR_ASSERT(json_key->private_key_id != NULL && - !strcmp(json_key->private_key_id, - "e6b5137873db8d2ef81e06a47289e6434ec8a165")); + strcmp(json_key->private_key_id, + "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); GPR_ASSERT(json_key->client_id != NULL && - !strcmp(json_key->client_id, - "777-abaslkan11hlb6nmim3bpspl31ud.apps." - "googleusercontent.com")); + strcmp(json_key->client_id, + "777-abaslkan11hlb6nmim3bpspl31ud.apps." + "googleusercontent.com") == 0); GPR_ASSERT(json_key->client_email != NULL && - !strcmp(json_key->client_email, - "777-abaslkan11hlb6nmim3bpspl31ud@developer." - "gserviceaccount.com")); - if (scope != NULL) GPR_ASSERT(!strcmp(scope, test_scope)); + strcmp(json_key->client_email, + "777-abaslkan11hlb6nmim3bpspl31ud@developer." + "gserviceaccount.com") == 0); + if (scope != NULL) GPR_ASSERT(strcmp(scope, test_scope) == 0); GPR_ASSERT(!gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime)); } @@ -517,12 +520,12 @@ static void validate_service_account_http_request( GPR_ASSERT(!memcmp(expected_body, body, body_size)); gpr_free(expected_body); GPR_ASSERT(request->use_ssl); - GPR_ASSERT(!strcmp(request->host, "www.googleapis.com")); - GPR_ASSERT(!strcmp(request->path, "/oauth2/v3/token")); + GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0); + GPR_ASSERT(strcmp(request->path, "/oauth2/v3/token") == 0); GPR_ASSERT(request->hdr_count == 1); - GPR_ASSERT(!strcmp(request->hdrs[0].key, "Content-Type")); - GPR_ASSERT( - !strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded")); + GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0); + GPR_ASSERT(strcmp(request->hdrs[0].value, + "application/x-www-form-urlencoded") == 0); } static int service_account_httpcli_post_success( @@ -626,12 +629,12 @@ static void on_jwt_creds_get_metadata_success(void *user_data, gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt); GPR_ASSERT(status == GRPC_CREDENTIALS_OK); GPR_ASSERT(num_md == 1); - GPR_ASSERT( - !strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), "Authorization")); - GPR_ASSERT( - !strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), expected_md_value)); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), + "Authorization") == 0); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), + expected_md_value) == 0); GPR_ASSERT(user_data != NULL); - GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); + GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); gpr_free(expected_md_value); } @@ -642,7 +645,7 @@ static void on_jwt_creds_get_metadata_failure(void *user_data, GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); GPR_ASSERT(num_md == 0); GPR_ASSERT(user_data != NULL); - GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); + GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); } static void test_jwt_creds_success(void) { diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c index fae911721a..ca5b889102 100644 --- a/test/core/security/json_token_test.c +++ b/test/core/security/json_token_test.c @@ -102,18 +102,18 @@ static void test_parse_json_key_success(void) { grpc_auth_json_key_create_from_string(json_string); GPR_ASSERT(grpc_auth_json_key_is_valid(&json_key)); GPR_ASSERT(json_key.type != NULL && - !(strcmp(json_key.type, "service_account"))); + strcmp(json_key.type, "service_account") == 0); GPR_ASSERT(json_key.private_key_id != NULL && - !strcmp(json_key.private_key_id, - "e6b5137873db8d2ef81e06a47289e6434ec8a165")); + strcmp(json_key.private_key_id, + "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); GPR_ASSERT(json_key.client_id != NULL && - !strcmp(json_key.client_id, - "777-abaslkan11hlb6nmim3bpspl31ud.apps." - "googleusercontent.com")); + strcmp(json_key.client_id, + "777-abaslkan11hlb6nmim3bpspl31ud.apps." + "googleusercontent.com") == 0); GPR_ASSERT(json_key.client_email != NULL && - !strcmp(json_key.client_email, - "777-abaslkan11hlb6nmim3bpspl31ud@developer." - "gserviceaccount.com")); + strcmp(json_key.client_email, + "777-abaslkan11hlb6nmim3bpspl31ud@developer." + "gserviceaccount.com") == 0); GPR_ASSERT(json_key.private_key != NULL); gpr_free(json_string); grpc_auth_json_key_destruct(&json_key); @@ -248,15 +248,16 @@ static void check_jwt_header(grpc_json *header) { } GPR_ASSERT(alg != NULL); GPR_ASSERT(alg->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(alg->value, "RS256")); + GPR_ASSERT(strcmp(alg->value, "RS256") == 0); GPR_ASSERT(typ != NULL); GPR_ASSERT(typ->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(typ->value, "JWT")); + GPR_ASSERT(strcmp(typ->value, "JWT") == 0); GPR_ASSERT(kid != NULL); GPR_ASSERT(kid->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(kid->value, "e6b5137873db8d2ef81e06a47289e6434ec8a165")); + GPR_ASSERT(strcmp(kid->value, + "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); } static void check_jwt_claim(grpc_json *claim, const char *expected_audience, @@ -290,27 +291,26 @@ static void check_jwt_claim(grpc_json *claim, const char *expected_audience, GPR_ASSERT(iss != NULL); GPR_ASSERT(iss->type == GRPC_JSON_STRING); - GPR_ASSERT( - !strcmp( - iss->value, - "777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount.com")); + GPR_ASSERT(strcmp(iss->value, + "777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount.com") + ==0); if (expected_scope != NULL) { GPR_ASSERT(scope != NULL); GPR_ASSERT(sub == NULL); GPR_ASSERT(scope->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(scope->value, expected_scope)); + GPR_ASSERT(strcmp(scope->value, expected_scope) == 0); } else { /* Claims without scope must have a sub. */ GPR_ASSERT(scope == NULL); GPR_ASSERT(sub != NULL); GPR_ASSERT(sub->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(iss->value, sub->value)); + GPR_ASSERT(strcmp(iss->value, sub->value) == 0); } GPR_ASSERT(aud != NULL); GPR_ASSERT(aud->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(aud->value, expected_audience)); + GPR_ASSERT(strcmp(aud->value, expected_audience) == 0); GPR_ASSERT(exp != NULL); GPR_ASSERT(exp->type == GRPC_JSON_NUMBER); diff --git a/test/core/statistics/census_log_tests.h b/test/core/statistics/census_log_tests.h index f829ab3683..28bde086f3 100644 --- a/test/core/statistics/census_log_tests.h +++ b/test/core/statistics/census_log_tests.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_STATISTICS_LOG_TESTS_H__ -#define __GRPC_TEST_STATISTICS_LOG_TESTS_H__ +#ifndef GRPC_TEST_CORE_STATISTICS_CENSUS_LOG_TESTS_H +#define GRPC_TEST_CORE_STATISTICS_CENSUS_LOG_TESTS_H void test_invalid_record_size(); void test_end_write_with_different_size(); @@ -48,4 +48,4 @@ void test_multiple_writers(); void test_performance(); void test_small_log(); -#endif /* __GRPC_TEST_STATISTICS_LOG_TESTS_H__ */ +#endif /* GRPC_TEST_CORE_STATISTICS_CENSUS_LOG_TESTS_H */ diff --git a/test/core/support/env_test.c b/test/core/support/env_test.c index 1f16af87a5..aedf9313f3 100644 --- a/test/core/support/env_test.c +++ b/test/core/support/env_test.c @@ -53,7 +53,7 @@ static void test_setenv_getenv(void) { gpr_setenv(name, value); retrieved_value = gpr_getenv(name); GPR_ASSERT(retrieved_value != NULL); - GPR_ASSERT(!strcmp(value, retrieved_value)); + GPR_ASSERT(strcmp(value, retrieved_value) == 0); gpr_free(retrieved_value); } diff --git a/test/core/support/slice_buffer_test.c b/test/core/support/slice_buffer_test.c index 8301795dbf..a48278434f 100644 --- a/test/core/support/slice_buffer_test.c +++ b/test/core/support/slice_buffer_test.c @@ -62,8 +62,13 @@ int main(int argc, char **argv) { } GPR_ASSERT(buf.count > 0); GPR_ASSERT(buf.length == 50); - gpr_slice_unref(aaa); - gpr_slice_unref(bb); + for (i = 0; i < 10; i++) { + gpr_slice_buffer_pop(&buf); + gpr_slice_unref(aaa); + gpr_slice_unref(bb); + } + GPR_ASSERT(buf.count == 0); + GPR_ASSERT(buf.length == 0); gpr_slice_buffer_destroy(&buf); return 0; diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index 3653c5a1b0..f0420896ee 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -31,7 +31,7 @@ * */ -#include "src/core/surface/lame_client.h" +#include <grpc/grpc.h> #include "test/core/end2end/cq_verifier.h" #include "test/core/util/test_config.h" diff --git a/test/core/transport/chttp2/stream_map_test.c b/test/core/transport/chttp2/stream_map_test.c index 6b91bdf14f..d678e0af73 100644 --- a/test/core/transport/chttp2/stream_map_test.c +++ b/test/core/transport/chttp2/stream_map_test.c @@ -213,7 +213,7 @@ int main(int argc, char **argv) { test_empty_find(); test_double_deletion(); - while (n < 10000000) { + while (n < 100000) { test_basic_add_find(n); test_delete_evens_sweep(n); test_delete_evens_incremental(n); diff --git a/test/core/transport/transport_end2end_tests.h b/test/core/transport/transport_end2end_tests.h index 3dc2b9b067..1edffe9a79 100644 --- a/test/core/transport/transport_end2end_tests.h +++ b/test/core/transport/transport_end2end_tests.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_TRANSPORT_TRANSPORT_END2END_TESTS_H__ -#define __GRPC_TEST_TRANSPORT_TRANSPORT_END2END_TESTS_H__ +#ifndef GRPC_TEST_CORE_TRANSPORT_TRANSPORT_END2END_TESTS_H +#define GRPC_TEST_CORE_TRANSPORT_TRANSPORT_END2END_TESTS_H #include "src/core/transport/transport.h" @@ -65,4 +65,4 @@ typedef struct grpc_transport_test_config { /* Run the test suite on one configuration */ void grpc_transport_end2end_tests(grpc_transport_test_config *config); -#endif /* __GRPC_TEST_TRANSPORT_TRANSPORT_END2END_TESTS_H__ */ +#endif /* GRPC_TEST_CORE_TRANSPORT_TRANSPORT_END2END_TESTS_H */ diff --git a/test/core/util/grpc_profiler.c b/test/core/util/grpc_profiler.c index 35b9361c70..d5b6cfeef1 100644 --- a/test/core/util/grpc_profiler.c +++ b/test/core/util/grpc_profiler.c @@ -44,7 +44,7 @@ void grpc_profiler_stop() { ProfilerStop(); } void grpc_profiler_start(const char *filename) { gpr_log(GPR_DEBUG, - "You do not have google-perftools installed, profiling is disabled"); + "You do not have google-perftools installed, profiling is disabled [for %s]", filename); gpr_log(GPR_DEBUG, "To install on ubuntu: sudo apt-get install google-perftools " "libgoogle-perftools-dev"); diff --git a/test/core/util/grpc_profiler.h b/test/core/util/grpc_profiler.h index a31fcc1db5..347a1d39d5 100644 --- a/test/core/util/grpc_profiler.h +++ b/test/core/util/grpc_profiler.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_UTIL_GRPC_PROFILER_H__ -#define __GRPC_TEST_UTIL_GRPC_PROFILER_H__ +#ifndef GRPC_TEST_CORE_UTIL_GRPC_PROFILER_H +#define GRPC_TEST_CORE_UTIL_GRPC_PROFILER_H #ifdef __cplusplus extern "C" { @@ -45,4 +45,4 @@ void grpc_profiler_stop(); } #endif /* __cplusplus */ -#endif /* __GRPC_TEST_UTIL_GRPC_PROFILER_H__ */ +#endif /* GRPC_TEST_CORE_UTIL_GRPC_PROFILER_H */ diff --git a/test/core/util/parse_hexstring.h b/test/core/util/parse_hexstring.h index 3fce0c9f7a..22bbd1756f 100644 --- a/test/core/util/parse_hexstring.h +++ b/test/core/util/parse_hexstring.h @@ -31,11 +31,11 @@ * */ -#ifndef __GRPC_TEST_UTIL_PARSE_HEXSTRING_H_ -#define __GRPC_TEST_UTIL_PARSE_HEXSTRING_H_ +#ifndef GRPC_TEST_CORE_UTIL_PARSE_HEXSTRING_H +#define GRPC_TEST_CORE_UTIL_PARSE_HEXSTRING_H #include <grpc/support/slice.h> gpr_slice parse_hexstring(const char *hexstring); -#endif /* __GRPC_TEST_UTIL_PARSE_HEXSTRING_H_ */ +#endif /* GRPC_TEST_CORE_UTIL_PARSE_HEXSTRING_H */ diff --git a/test/core/util/port.h b/test/core/util/port.h index 2a12ab985e..b516ec5a48 100644 --- a/test/core/util/port.h +++ b/test/core/util/port.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_UTIL_PORT_H__ -#define __GRPC_TEST_UTIL_PORT_H__ +#ifndef GRPC_TEST_CORE_UTIL_PORT_H +#define GRPC_TEST_CORE_UTIL_PORT_H #ifdef __cplusplus extern "C" { @@ -49,4 +49,4 @@ int grpc_pick_unused_port_or_die(); } #endif -#endif /* __GRPC_TEST_UTIL_PORT_H__ */ +#endif /* GRPC_TEST_CORE_UTIL_PORT_H */ diff --git a/test/core/util/slice_splitter.h b/test/core/util/slice_splitter.h index b67fe737cb..1ce1c097e2 100644 --- a/test/core/util/slice_splitter.h +++ b/test/core/util/slice_splitter.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_UTIL_SLICE_SPLITTER_H__ -#define __GRPC_TEST_UTIL_SLICE_SPLITTER_H__ +#ifndef GRPC_TEST_CORE_UTIL_SLICE_SPLITTER_H +#define GRPC_TEST_CORE_UTIL_SLICE_SPLITTER_H /* utility function to split/merge slices together to help create test cases */ @@ -65,4 +65,4 @@ gpr_slice grpc_slice_merge(gpr_slice *slices, size_t nslices); const char *grpc_slice_split_mode_name(grpc_slice_split_mode mode); -#endif /* __GRPC_TEST_UTIL_SLICE_SPLITTER_H__ */ +#endif /* GRPC_TEST_CORE_UTIL_SLICE_SPLITTER_H */ diff --git a/test/core/util/test_config.h b/test/core/util/test_config.h index 5292c7b525..668a069f26 100644 --- a/test/core/util/test_config.h +++ b/test/core/util/test_config.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPC_TEST_UTIL_TEST_CONFIG_H__ -#define __GRPC_TEST_UTIL_TEST_CONFIG_H__ +#ifndef GRPC_TEST_CORE_UTIL_TEST_CONFIG_H +#define GRPC_TEST_CORE_UTIL_TEST_CONFIG_H #include <grpc/support/time.h> @@ -65,4 +65,4 @@ void grpc_test_init(int argc, char **argv); } #endif /* __cplusplus */ -#endif /* __GRPC_TEST_UTIL_TEST_CONFIG_H__ */ +#endif /* GRPC_TEST_CORE_UTIL_TEST_CONFIG_H */ diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc index dc8d76d7ef..59ca33cc29 100644 --- a/test/cpp/client/credentials_test.cc +++ b/test/cpp/client/credentials_test.cc @@ -47,8 +47,7 @@ class CredentialsTest : public ::testing::Test { TEST_F(CredentialsTest, InvalidServiceAccountCreds) { std::unique_ptr<Credentials> bad1 = - CredentialsFactory::ServiceAccountCredentials("", "", - std::chrono::seconds(1)); + ServiceAccountCredentials("", "", std::chrono::seconds(1)); EXPECT_EQ(nullptr, bad1.get()); } diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 5a2762d049..70df9e14b2 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -47,6 +47,7 @@ #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> #include <grpc++/status.h> #include <grpc++/stream.h> #include "test/core/util/port.h" @@ -65,9 +66,7 @@ namespace testing { namespace { -void* tag(int i) { - return (void*)(gpr_intptr)i; -} +void* tag(int i) { return (void*)(gpr_intptr)i; } void verify_ok(CompletionQueue* cq, int i, bool expect_ok) { bool ok; @@ -86,7 +85,7 @@ class AsyncEnd2endTest : public ::testing::Test { server_address_ << "localhost:" << port; // Setup server ServerBuilder builder; - builder.AddPort(server_address_.str()); + builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials()); builder.RegisterAsyncService(&service_); server_ = builder.BuildAndStart(); } @@ -104,23 +103,15 @@ class AsyncEnd2endTest : public ::testing::Test { } void ResetStub() { - std::shared_ptr<ChannelInterface> channel = - CreateChannelDeprecated(server_address_.str(), ChannelArguments()); + std::shared_ptr<ChannelInterface> channel = CreateChannel( + server_address_.str(), InsecureCredentials(), ChannelArguments()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel)); } - void server_ok(int i) { - verify_ok(&srv_cq_, i, true); - } - void client_ok(int i) { - verify_ok(&cli_cq_, i , true); - } - void server_fail(int i) { - verify_ok(&srv_cq_, i, false); - } - void client_fail(int i) { - verify_ok(&cli_cq_, i, false); - } + void server_ok(int i) { verify_ok(&srv_cq_, i, true); } + void client_ok(int i) { verify_ok(&cli_cq_, i, true); } + void server_fail(int i) { verify_ok(&srv_cq_, i, false); } + void client_fail(int i) { verify_ok(&cli_cq_, i, false); } void SendRpc(int num_rpcs) { for (int i = 0; i < num_rpcs; i++) { @@ -135,12 +126,11 @@ class AsyncEnd2endTest : public ::testing::Test { grpc::ServerAsyncResponseWriter<EchoResponse> response_writer(&srv_ctx); send_request.set_message("Hello"); - std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > - response_reader(stub_->Echo( - &cli_ctx, send_request, &cli_cq_, tag(1))); + std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, &cli_cq_, tag(1))); - service_.RequestEcho( - &srv_ctx, &recv_request, &response_writer, &srv_cq_, tag(2)); + service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, &srv_cq_, + tag(2)); server_ok(2); EXPECT_EQ(send_request.message(), recv_request.message()); @@ -191,10 +181,9 @@ TEST_F(AsyncEnd2endTest, SimpleClientStreaming) { send_request.set_message("Hello"); std::unique_ptr<ClientAsyncWriter<EchoRequest> > cli_stream( - stub_->RequestStream(&cli_ctx, &recv_response, &cli_cq_, tag(1))); + stub_->AsyncRequestStream(&cli_ctx, &recv_response, &cli_cq_, tag(1))); - service_.RequestRequestStream( - &srv_ctx, &srv_stream, &srv_cq_, tag(2)); + service_.RequestRequestStream(&srv_ctx, &srv_stream, &srv_cq_, tag(2)); server_ok(2); client_ok(1); @@ -245,10 +234,10 @@ TEST_F(AsyncEnd2endTest, SimpleServerStreaming) { send_request.set_message("Hello"); std::unique_ptr<ClientAsyncReader<EchoResponse> > cli_stream( - stub_->ResponseStream(&cli_ctx, send_request, &cli_cq_, tag(1))); + stub_->AsyncResponseStream(&cli_ctx, send_request, &cli_cq_, tag(1))); - service_.RequestResponseStream( - &srv_ctx, &recv_request, &srv_stream, &srv_cq_, tag(2)); + service_.RequestResponseStream(&srv_ctx, &recv_request, &srv_stream, &srv_cq_, + tag(2)); server_ok(2); client_ok(1); @@ -296,10 +285,9 @@ TEST_F(AsyncEnd2endTest, SimpleBidiStreaming) { send_request.set_message("Hello"); std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse> > - cli_stream(stub_->BidiStream(&cli_ctx, &cli_cq_, tag(1))); + cli_stream(stub_->AsyncBidiStream(&cli_ctx, &cli_cq_, tag(1))); - service_.RequestBidiStream( - &srv_ctx, &srv_stream, &srv_cq_, tag(2)); + service_.RequestBidiStream(&srv_ctx, &srv_stream, &srv_cq_, tag(2)); server_ok(2); client_ok(1); @@ -355,10 +343,10 @@ TEST_F(AsyncEnd2endTest, ClientInitialMetadataRpc) { cli_ctx.AddMetadata(meta2.first, meta2.second); std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( - stub_->Echo(&cli_ctx, send_request, &cli_cq_, tag(1))); + stub_->AsyncEcho(&cli_ctx, send_request, &cli_cq_, tag(1))); - service_.RequestEcho( - &srv_ctx, &recv_request, &response_writer, &srv_cq_, tag(2)); + service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, &srv_cq_, + tag(2)); server_ok(2); EXPECT_EQ(send_request.message(), recv_request.message()); auto client_initial_metadata = srv_ctx.client_metadata(); @@ -397,10 +385,10 @@ TEST_F(AsyncEnd2endTest, ServerInitialMetadataRpc) { std::pair<grpc::string, grpc::string> meta2("key2", "val2"); std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( - stub_->Echo(&cli_ctx, send_request, &cli_cq_, tag(1))); + stub_->AsyncEcho(&cli_ctx, send_request, &cli_cq_, tag(1))); - service_.RequestEcho( - &srv_ctx, &recv_request, &response_writer, &srv_cq_, tag(2)); + service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, &srv_cq_, + tag(2)); server_ok(2); EXPECT_EQ(send_request.message(), recv_request.message()); srv_ctx.AddInitialMetadata(meta1.first, meta1.second); @@ -445,10 +433,10 @@ TEST_F(AsyncEnd2endTest, ServerTrailingMetadataRpc) { std::pair<grpc::string, grpc::string> meta2("key2", "val2"); std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( - stub_->Echo(&cli_ctx, send_request, &cli_cq_, tag(1))); + stub_->AsyncEcho(&cli_ctx, send_request, &cli_cq_, tag(1))); - service_.RequestEcho( - &srv_ctx, &recv_request, &response_writer, &srv_cq_, tag(2)); + service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, &srv_cq_, + tag(2)); server_ok(2); EXPECT_EQ(send_request.message(), recv_request.message()); response_writer.SendInitialMetadata(tag(3)); @@ -462,7 +450,6 @@ TEST_F(AsyncEnd2endTest, ServerTrailingMetadataRpc) { server_ok(4); - response_reader->Finish(&recv_response, &recv_status, tag(5)); client_ok(5); EXPECT_EQ(send_response.message(), recv_response.message()); @@ -491,20 +478,22 @@ TEST_F(AsyncEnd2endTest, MetadataRpc) { std::pair<grpc::string, grpc::string> meta2( "key2-bin", {"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", 13}); std::pair<grpc::string, grpc::string> meta3("key3", "val3"); - std::pair<grpc::string, grpc::string> meta6("key4-bin", + std::pair<grpc::string, grpc::string> meta6( + "key4-bin", {"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d", 14}); std::pair<grpc::string, grpc::string> meta5("key5", "val5"); - std::pair<grpc::string, grpc::string> meta4("key6-bin", + std::pair<grpc::string, grpc::string> meta4( + "key6-bin", {"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee", 15}); cli_ctx.AddMetadata(meta1.first, meta1.second); cli_ctx.AddMetadata(meta2.first, meta2.second); std::unique_ptr<ClientAsyncResponseReader<EchoResponse> > response_reader( - stub_->Echo(&cli_ctx, send_request, &cli_cq_, tag(1))); + stub_->AsyncEcho(&cli_ctx, send_request, &cli_cq_, tag(1))); - service_.RequestEcho( - &srv_ctx, &recv_request, &response_writer, &srv_cq_, tag(2)); + service_.RequestEcho(&srv_ctx, &recv_request, &response_writer, &srv_cq_, + tag(2)); server_ok(2); EXPECT_EQ(send_request.message(), recv_request.message()); auto client_initial_metadata = srv_ctx.client_metadata(); @@ -531,7 +520,6 @@ TEST_F(AsyncEnd2endTest, MetadataRpc) { server_ok(5); - response_reader->Finish(&recv_response, &recv_status, tag(6)); client_ok(6); EXPECT_EQ(send_response.message(), recv_response.message()); diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 1d5dfc4e34..c586849349 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -47,6 +47,7 @@ #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> #include <grpc++/status.h> #include <grpc++/stream.h> #include "test/core/util/port.h" @@ -150,7 +151,7 @@ class End2endTest : public ::testing::Test { server_address_ << "localhost:" << port; // Setup server ServerBuilder builder; - builder.AddPort(server_address_.str()); + builder.AddPort(server_address_.str(), InsecureServerCredentials()); builder.RegisterService(&service_); builder.RegisterService(&dup_pkg_service_); builder.SetThreadPool(&thread_pool_); @@ -160,8 +161,8 @@ class End2endTest : public ::testing::Test { void TearDown() GRPC_OVERRIDE { server_->Shutdown(); } void ResetStub() { - std::shared_ptr<ChannelInterface> channel = - CreateChannelDeprecated(server_address_.str(), ChannelArguments()); + std::shared_ptr<ChannelInterface> channel = CreateChannel( + server_address_.str(), InsecureCredentials(), ChannelArguments()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel)); } @@ -371,8 +372,8 @@ TEST_F(End2endTest, BidiStream) { // Talk to the two services with the same name but different package names. // The two stubs are created on the same channel. TEST_F(End2endTest, DiffPackageServices) { - std::shared_ptr<ChannelInterface> channel = - CreateChannelDeprecated(server_address_.str(), ChannelArguments()); + std::shared_ptr<ChannelInterface> channel = CreateChannel( + server_address_.str(), InsecureCredentials(), ChannelArguments()); EchoRequest request; EchoResponse response; @@ -397,8 +398,7 @@ TEST_F(End2endTest, DiffPackageServices) { // rpc and stream should fail on bad credentials. TEST_F(End2endTest, BadCredentials) { std::unique_ptr<Credentials> bad_creds = - CredentialsFactory::ServiceAccountCredentials("", "", - std::chrono::seconds(1)); + ServiceAccountCredentials("", "", std::chrono::seconds(1)); EXPECT_EQ(nullptr, bad_creds.get()); std::shared_ptr<ChannelInterface> channel = CreateChannel(server_address_.str(), bad_creds, ChannelArguments()); diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index 73a6ad107d..132e6e9068 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -83,9 +83,10 @@ DEFINE_string(oauth_scope, "", "Scope for OAuth tokens."); using grpc::ChannelInterface; using grpc::ClientContext; +using grpc::ComputeEngineCredentials; using grpc::CreateTestChannel; using grpc::Credentials; -using grpc::CredentialsFactory; +using grpc::ServiceAccountCredentials; using grpc::testing::ResponseParameters; using grpc::testing::SimpleRequest; using grpc::testing::SimpleResponse; @@ -97,8 +98,8 @@ using grpc::testing::TestService; // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } +namespace google {} +namespace gflags {} using namespace google; using namespace gflags; @@ -136,14 +137,14 @@ std::shared_ptr<ChannelInterface> CreateChannelForTestCase( std::unique_ptr<Credentials> creds; GPR_ASSERT(FLAGS_enable_ssl); grpc::string json_key = GetServiceAccountJsonKey(); - creds = CredentialsFactory::ServiceAccountCredentials( - json_key, FLAGS_oauth_scope, std::chrono::hours(1)); + creds = ServiceAccountCredentials(json_key, FLAGS_oauth_scope, + std::chrono::hours(1)); return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_enable_ssl, FLAGS_use_prod_roots, creds); } else if (test_case == "compute_engine_creds") { std::unique_ptr<Credentials> creds; GPR_ASSERT(FLAGS_enable_ssl); - creds = CredentialsFactory::ComputeEngineCredentials(); + creds = ComputeEngineCredentials(); return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_enable_ssl, FLAGS_use_prod_roots, creds); } else if (test_case == "jwt_token_creds") { @@ -210,7 +211,7 @@ void DoComputeEngineCreds() { GPR_ASSERT(!response.username().empty()); GPR_ASSERT(response.username().c_str() == FLAGS_default_service_account); GPR_ASSERT(!response.oauth_scope().empty()); - const char *oauth_scope_str = response.oauth_scope().c_str(); + const char* oauth_scope_str = response.oauth_scope().c_str(); GPR_ASSERT(FLAGS_oauth_scope.find(oauth_scope_str) != grpc::string::npos); gpr_log(GPR_INFO, "Large unary with compute engine creds done."); } @@ -229,7 +230,7 @@ void DoServiceAccountCreds() { GPR_ASSERT(!response.oauth_scope().empty()); grpc::string json_key = GetServiceAccountJsonKey(); GPR_ASSERT(json_key.find(response.username()) != grpc::string::npos); - const char *oauth_scope_str = response.oauth_scope().c_str(); + const char* oauth_scope_str = response.oauth_scope().c_str(); GPR_ASSERT(FLAGS_oauth_scope.find(oauth_scope_str) != grpc::string::npos); gpr_log(GPR_INFO, "Large unary with service account creds done."); } diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc index 9810ff6622..743482e967 100644 --- a/test/cpp/interop/server.cc +++ b/test/cpp/interop/server.cc @@ -60,7 +60,6 @@ using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::ServerCredentials; -using grpc::ServerCredentialsFactory; using grpc::ServerReader; using grpc::ServerReaderWriter; using grpc::ServerWriter; @@ -78,8 +77,8 @@ using grpc::Status; // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } +namespace google {} +namespace gflags {} using namespace google; using namespace gflags; @@ -211,15 +210,14 @@ void RunServer() { SimpleResponse response; ServerBuilder builder; - builder.AddPort(server_address.str()); builder.RegisterService(&service); + std::shared_ptr<ServerCredentials> creds = grpc::InsecureServerCredentials(); if (FLAGS_enable_ssl) { SslServerCredentialsOptions ssl_opts = { "", {{test_server1_key, test_server1_cert}}}; - std::shared_ptr<ServerCredentials> creds = - ServerCredentialsFactory::SslCredentials(ssl_opts); - builder.SetCredentials(creds); + creds = grpc::SslServerCredentials(ssl_opts); } + builder.AddPort(server_address.str(), creds); std::unique_ptr<Server> server(builder.BuildAndStart()); gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str()); while (!got_sigint) { diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client.cc deleted file mode 100644 index 11c39eb4f5..0000000000 --- a/test/cpp/qps/client.cc +++ /dev/null @@ -1,252 +0,0 @@ -/* - * - * 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 <cassert> -#include <memory> -#include <string> -#include <thread> -#include <vector> -#include <sstream> - -#include <grpc/grpc.h> -#include <grpc/support/histogram.h> -#include <grpc/support/log.h> -#include <gflags/gflags.h> -#include <grpc++/client_context.h> -#include <grpc++/status.h> -#include "test/core/util/grpc_profiler.h" -#include "test/cpp/util/create_test_channel.h" -#include "test/cpp/qps/qpstest.pb.h" - -DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); -DEFINE_int32(server_port, 0, "Server port."); -DEFINE_string(server_host, "127.0.0.1", "Server host."); -DEFINE_int32(client_threads, 4, "Number of client threads."); - -// We have a configurable number of channels for sending RPCs. -// RPCs are sent round-robin on the available channels by the -// various threads. Interesting cases are 1 global channel or -// 1 per-thread channel, but we can support any number. -// The channels are assigned round-robin on an RPC by RPC basis -// rather than just at initialization time in order to also measure the -// impact of cache thrashing caused by channel changes. This is an issue -// if you are not in one of the above "interesting cases" -DEFINE_int32(client_channels, 4, "Number of client channels."); - -DEFINE_int32(num_rpcs, 1000, "Number of RPCs per thread."); -DEFINE_int32(payload_size, 1, "Payload size in bytes"); - -// Alternatively, specify parameters for test as a workload so that multiple -// tests are initiated back-to-back. This is convenient for keeping a borg -// allocation consistent. This is a space-separated list of -// [threads channels num_rpcs payload_size ]* -DEFINE_string(workload, "", "Workload parameters"); - -using grpc::ChannelInterface; -using grpc::CreateTestChannel; -using grpc::testing::ServerStats; -using grpc::testing::SimpleRequest; -using grpc::testing::SimpleResponse; -using grpc::testing::StatsRequest; -using grpc::testing::TestService; - -// In some distros, gflags is in the namespace google, and in some others, -// in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } -using namespace google; -using namespace gflags; - -static double now() { - gpr_timespec tv = gpr_now(); - return 1e9 * tv.tv_sec + tv.tv_nsec; -} - -void RunTest(const int client_threads, const int client_channels, - const int num_rpcs, const int payload_size) { - gpr_log(GPR_INFO, - "QPS test with parameters\n" - "enable_ssl = %d\n" - "client_channels = %d\n" - "client_threads = %d\n" - "num_rpcs = %d\n" - "payload_size = %d\n" - "server_host:server_port = %s:%d\n\n", - FLAGS_enable_ssl, client_channels, client_threads, num_rpcs, - payload_size, FLAGS_server_host.c_str(), FLAGS_server_port); - - std::ostringstream oss; - oss << FLAGS_server_host << ":" << FLAGS_server_port; - - class ClientChannelInfo { - public: - explicit ClientChannelInfo(const grpc::string &server) - : channel_(CreateTestChannel(server, FLAGS_enable_ssl)), - stub_(TestService::NewStub(channel_)) {} - ChannelInterface *get_channel() { return channel_.get(); } - TestService::Stub *get_stub() { return stub_.get(); } - - private: - std::shared_ptr<ChannelInterface> channel_; - std::unique_ptr<TestService::Stub> stub_; - }; - - std::vector<ClientChannelInfo> channels; - for (int i = 0; i < client_channels; i++) { - channels.push_back(ClientChannelInfo(oss.str())); - } - - std::vector<std::thread> threads; // Will add threads when ready to execute - std::vector< ::gpr_histogram *> thread_stats(client_threads); - - TestService::Stub *stub_stats = channels[0].get_stub(); - grpc::ClientContext context_stats_begin; - StatsRequest stats_request; - ServerStats server_stats_begin; - stats_request.set_test_num(0); - grpc::Status status_beg = stub_stats->CollectServerStats( - &context_stats_begin, stats_request, &server_stats_begin); - - grpc_profiler_start("qps_client.prof"); - - for (int i = 0; i < client_threads; i++) { - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - thread_stats[i] = hist; - - threads.push_back( - std::thread([hist, client_threads, client_channels, num_rpcs, - payload_size, &channels](int channel_num) { - SimpleRequest request; - SimpleResponse response; - request.set_response_type( - grpc::testing::PayloadType::COMPRESSABLE); - request.set_response_size(payload_size); - - for (int j = 0; j < num_rpcs; j++) { - TestService::Stub *stub = - channels[channel_num].get_stub(); - double start = now(); - grpc::ClientContext context; - grpc::Status s = - stub->UnaryCall(&context, request, &response); - gpr_histogram_add(hist, now() - start); - - GPR_ASSERT((s.code() == grpc::StatusCode::OK) && - (response.payload().type() == - grpc::testing::PayloadType::COMPRESSABLE) && - (response.payload().body().length() == - static_cast<size_t>(payload_size))); - - // Now do runtime round-robin assignment of the next - // channel number - channel_num += client_threads; - channel_num %= client_channels; - } - }, - i % client_channels)); - } - - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - for (auto &t : threads) { - t.join(); - } - - grpc_profiler_stop(); - - for (int i = 0; i < client_threads; i++) { - gpr_histogram *h = thread_stats[i]; - gpr_log(GPR_INFO, "latency at thread %d (50/90/95/99/99.9): %f/%f/%f/%f/%f", - i, gpr_histogram_percentile(h, 50), gpr_histogram_percentile(h, 90), - gpr_histogram_percentile(h, 95), gpr_histogram_percentile(h, 99), - gpr_histogram_percentile(h, 99.9)); - gpr_histogram_merge(hist, h); - gpr_histogram_destroy(h); - } - - gpr_log( - GPR_INFO, - "latency across %d threads with %d channels and %d payload " - "(50/90/95/99/99.9): %f / %f / %f / %f / %f", - client_threads, client_channels, payload_size, - gpr_histogram_percentile(hist, 50), gpr_histogram_percentile(hist, 90), - gpr_histogram_percentile(hist, 95), gpr_histogram_percentile(hist, 99), - gpr_histogram_percentile(hist, 99.9)); - gpr_histogram_destroy(hist); - - grpc::ClientContext context_stats_end; - ServerStats server_stats_end; - grpc::Status status_end = stub_stats->CollectServerStats( - &context_stats_end, stats_request, &server_stats_end); - - double elapsed = server_stats_end.time_now() - server_stats_begin.time_now(); - int total_rpcs = client_threads * num_rpcs; - double utime = server_stats_end.time_user() - server_stats_begin.time_user(); - double stime = - server_stats_end.time_system() - server_stats_begin.time_system(); - gpr_log(GPR_INFO, - "Elapsed time: %.3f\n" - "RPC Count: %d\n" - "QPS: %.3f\n" - "System time: %.3f\n" - "User time: %.3f\n" - "Resource usage: %.1f%%\n", - elapsed, total_rpcs, total_rpcs / elapsed, stime, utime, - (stime + utime) / elapsed * 100.0); -} - -int main(int argc, char **argv) { - grpc_init(); - ParseCommandLineFlags(&argc, &argv, true); - - GPR_ASSERT(FLAGS_server_port); - - if (FLAGS_workload.length() == 0) { - RunTest(FLAGS_client_threads, FLAGS_client_channels, FLAGS_num_rpcs, - FLAGS_payload_size); - } else { - std::istringstream workload(FLAGS_workload); - int client_threads, client_channels, num_rpcs, payload_size; - workload >> client_threads; - while (!workload.eof()) { - workload >> client_channels >> num_rpcs >> payload_size; - RunTest(client_threads, client_channels, num_rpcs, payload_size); - workload >> client_threads; - } - gpr_log(GPR_INFO, "Done with specified workload."); - } - - grpc_shutdown(); - return 0; -} diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h new file mode 100644 index 0000000000..221fb30fc5 --- /dev/null +++ b/test/cpp/qps/client.h @@ -0,0 +1,173 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_CLIENT_H +#define TEST_QPS_CLIENT_H + +#include "test/cpp/qps/histogram.h" +#include "test/cpp/qps/timer.h" +#include "test/cpp/qps/qpstest.pb.h" + +#include <condition_variable> +#include <mutex> + +namespace grpc { +namespace testing { + +class Client { + public: + explicit Client(const ClientConfig& config) : timer_(new Timer) { + for (int i = 0; i < config.client_channels(); i++) { + channels_.push_back(ClientChannelInfo( + config.server_targets(i % config.server_targets_size()), config)); + } + request_.set_response_type(grpc::testing::PayloadType::COMPRESSABLE); + request_.set_response_size(config.payload_size()); + } + virtual ~Client() {} + + ClientStats Mark() { + Histogram latencies; + std::vector<Histogram> to_merge(threads_.size()); + for (size_t i = 0; i < threads_.size(); i++) { + threads_[i]->BeginSwap(&to_merge[i]); + } + std::unique_ptr<Timer> timer(new Timer); + timer_.swap(timer); + for (size_t i = 0; i < threads_.size(); i++) { + threads_[i]->EndSwap(); + latencies.Merge(&to_merge[i]); + } + + auto timer_result = timer->Mark(); + + ClientStats stats; + latencies.FillProto(stats.mutable_latencies()); + stats.set_time_elapsed(timer_result.wall); + stats.set_time_system(timer_result.system); + stats.set_time_user(timer_result.user); + return stats; + } + + protected: + SimpleRequest request_; + + class ClientChannelInfo { + public: + ClientChannelInfo(const grpc::string& target, const ClientConfig& config) + : channel_(CreateTestChannel(target, config.enable_ssl())), + stub_(TestService::NewStub(channel_)) {} + ChannelInterface* get_channel() { return channel_.get(); } + TestService::Stub* get_stub() { return stub_.get(); } + + private: + std::shared_ptr<ChannelInterface> channel_; + std::unique_ptr<TestService::Stub> stub_; + }; + std::vector<ClientChannelInfo> channels_; + + void StartThreads(size_t num_threads) { + for (size_t i = 0; i < num_threads; i++) { + threads_.emplace_back(new Thread(this, i)); + } + } + + void EndThreads() { threads_.clear(); } + + virtual void ThreadFunc(Histogram* histogram, size_t thread_idx) = 0; + + private: + class Thread { + public: + Thread(Client* client, size_t idx) + : done_(false), + new_(nullptr), + impl_([this, idx, client]() { + for (;;) { + // run the loop body + client->ThreadFunc(&histogram_, idx); + // lock, see if we're done + std::lock_guard<std::mutex> g(mu_); + if (done_) return; + // also check if we're marking, and swap out the histogram if so + if (new_) { + new_->Swap(&histogram_); + new_ = nullptr; + cv_.notify_one(); + } + } + }) {} + + ~Thread() { + { + std::lock_guard<std::mutex> g(mu_); + done_ = true; + } + impl_.join(); + } + + void BeginSwap(Histogram* n) { + std::lock_guard<std::mutex> g(mu_); + new_ = n; + } + + void EndSwap() { + std::unique_lock<std::mutex> g(mu_); + cv_.wait(g, [this]() { return new_ == nullptr; }); + } + + private: + Thread(const Thread&); + Thread& operator=(const Thread&); + + TestService::Stub* stub_; + ClientConfig config_; + std::mutex mu_; + std::condition_variable cv_; + bool done_; + Histogram* new_; + Histogram histogram_; + std::thread impl_; + }; + + std::vector<std::unique_ptr<Thread>> threads_; + std::unique_ptr<Timer> timer_; +}; + +std::unique_ptr<Client> CreateSynchronousClient(const ClientConfig& args); +std::unique_ptr<Client> CreateAsyncClient(const ClientConfig& args); + +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc new file mode 100644 index 0000000000..c6535bebf8 --- /dev/null +++ b/test/cpp/qps/client_async.cc @@ -0,0 +1,201 @@ +/* + * + * 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 <cassert> +#include <functional> +#include <memory> +#include <string> +#include <thread> +#include <vector> +#include <sstream> + +#include <grpc/grpc.h> +#include <grpc/support/histogram.h> +#include <grpc/support/log.h> +#include <gflags/gflags.h> +#include <grpc++/async_unary_call.h> +#include <grpc++/client_context.h> +#include <grpc++/status.h> +#include "test/core/util/grpc_profiler.h" +#include "test/cpp/util/create_test_channel.h" +#include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/timer.h" +#include "test/cpp/qps/client.h" + +namespace grpc { +namespace testing { + +class ClientRpcContext { + public: + ClientRpcContext() {} + virtual ~ClientRpcContext() {} + virtual bool RunNextState() = 0; // do next state, return false if steps done + virtual void StartNewClone() = 0; + static void *tag(ClientRpcContext *c) { return reinterpret_cast<void *>(c); } + static ClientRpcContext *detag(void *t) { + return reinterpret_cast<ClientRpcContext *>(t); + } + virtual void report_stats(Histogram *hist) = 0; +}; + +template <class RequestType, class ResponseType> +class ClientRpcContextUnaryImpl : public ClientRpcContext { + public: + ClientRpcContextUnaryImpl( + TestService::Stub *stub, const RequestType &req, + std::function< + std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>( + TestService::Stub *, grpc::ClientContext *, const RequestType &, + void *)> start_req, + std::function<void(grpc::Status, ResponseType *)> on_done) + : context_(), + stub_(stub), + req_(req), + response_(), + next_state_(&ClientRpcContextUnaryImpl::ReqSent), + callback_(on_done), + start_req_(start_req), + start_(Timer::Now()), + response_reader_( + start_req(stub_, &context_, req_, ClientRpcContext::tag(this))) {} + ~ClientRpcContextUnaryImpl() GRPC_OVERRIDE {} + bool RunNextState() GRPC_OVERRIDE { return (this->*next_state_)(); } + void report_stats(Histogram *hist) GRPC_OVERRIDE { + hist->Add((Timer::Now() - start_) * 1e9); + } + + void StartNewClone() GRPC_OVERRIDE { + new ClientRpcContextUnaryImpl(stub_, req_, start_req_, callback_); + } + + private: + bool ReqSent() { + next_state_ = &ClientRpcContextUnaryImpl::RespDone; + response_reader_->Finish(&response_, &status_, ClientRpcContext::tag(this)); + return true; + } + bool RespDone() { + next_state_ = &ClientRpcContextUnaryImpl::DoCallBack; + return false; + } + bool DoCallBack() { + callback_(status_, &response_); + return false; + } + grpc::ClientContext context_; + TestService::Stub *stub_; + RequestType req_; + ResponseType response_; + bool (ClientRpcContextUnaryImpl::*next_state_)(); + std::function<void(grpc::Status, ResponseType *)> callback_; + std::function<std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>( + TestService::Stub *, grpc::ClientContext *, const RequestType &, void *)> + start_req_; + grpc::Status status_; + double start_; + std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>> + response_reader_; +}; + +class AsyncClient GRPC_FINAL : public Client { + public: + explicit AsyncClient(const ClientConfig &config) : Client(config) { + for (int i = 0; i < config.async_client_threads(); i++) { + cli_cqs_.emplace_back(new CompletionQueue); + } + + auto payload_size = config.payload_size(); + auto check_done = [payload_size](grpc::Status s, SimpleResponse *response) { + GPR_ASSERT(s.IsOk() && (response->payload().type() == + grpc::testing::PayloadType::COMPRESSABLE) && + (response->payload().body().length() == + static_cast<size_t>(payload_size))); + }; + + int t = 0; + for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) { + for (auto &channel : channels_) { + auto *cq = cli_cqs_[t].get(); + t = (t + 1) % cli_cqs_.size(); + auto start_req = [cq](TestService::Stub *stub, grpc::ClientContext *ctx, + const SimpleRequest &request, void *tag) { + return stub->AsyncUnaryCall(ctx, request, cq, tag); + }; + + TestService::Stub *stub = channel.get_stub(); + const SimpleRequest &request = request_; + new ClientRpcContextUnaryImpl<SimpleRequest, SimpleResponse>( + stub, request, start_req, check_done); + } + } + + StartThreads(config.async_client_threads()); + } + + ~AsyncClient() GRPC_OVERRIDE { + EndThreads(); + + for (auto &cq : cli_cqs_) { + cq->Shutdown(); + void *got_tag; + bool ok; + while (cq->Next(&got_tag, &ok)) { + delete ClientRpcContext::detag(got_tag); + } + } + } + + void ThreadFunc(Histogram *histogram, size_t thread_idx) GRPC_OVERRIDE { + void *got_tag; + bool ok; + cli_cqs_[thread_idx]->Next(&got_tag, &ok); + + ClientRpcContext *ctx = ClientRpcContext::detag(got_tag); + if (ctx->RunNextState() == false) { + // call the callback and then delete it + ctx->report_stats(histogram); + ctx->RunNextState(); + ctx->StartNewClone(); + delete ctx; + } + } + + std::vector<std::unique_ptr<CompletionQueue>> cli_cqs_; +}; + +std::unique_ptr<Client> CreateAsyncClient(const ClientConfig &args) { + return std::unique_ptr<Client>(new AsyncClient(args)); +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc new file mode 100644 index 0000000000..7bb7231c6f --- /dev/null +++ b/test/cpp/qps/client_sync.cc @@ -0,0 +1,93 @@ +/* + * + * 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 <cassert> +#include <memory> +#include <mutex> +#include <string> +#include <thread> +#include <vector> +#include <sstream> + +#include <sys/signal.h> + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/histogram.h> +#include <grpc/support/log.h> +#include <grpc/support/host_port.h> +#include <gflags/gflags.h> +#include <grpc++/client_context.h> +#include <grpc++/status.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include "test/core/util/grpc_profiler.h" +#include "test/cpp/util/create_test_channel.h" +#include "test/cpp/qps/client.h" +#include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/histogram.h" +#include "test/cpp/qps/timer.h" + +namespace grpc { +namespace testing { + +class SynchronousClient GRPC_FINAL : public Client { + public: + SynchronousClient(const ClientConfig& config) : Client(config) { + size_t num_threads = + config.outstanding_rpcs_per_channel() * config.client_channels(); + responses_.resize(num_threads); + StartThreads(num_threads); + } + + ~SynchronousClient() { EndThreads(); } + + void ThreadFunc(Histogram* histogram, size_t thread_idx) { + auto* stub = channels_[thread_idx % channels_.size()].get_stub(); + double start = Timer::Now(); + grpc::ClientContext context; + grpc::Status s = + stub->UnaryCall(&context, request_, &responses_[thread_idx]); + histogram->Add((Timer::Now() - start) * 1e9); + } + + private: + std::vector<SimpleResponse> responses_; +}; + +std::unique_ptr<Client> CreateSynchronousClient(const ClientConfig& config) { + return std::unique_ptr<Client>(new SynchronousClient(config)); +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc new file mode 100644 index 0000000000..d29ca1de94 --- /dev/null +++ b/test/cpp/qps/driver.cc @@ -0,0 +1,210 @@ +/* + * + * 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 "test/cpp/qps/driver.h" +#include "src/core/support/env.h" +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/host_port.h> +#include <grpc++/channel_arguments.h> +#include <grpc++/client_context.h> +#include <grpc++/create_channel.h> +#include <grpc++/stream.h> +#include <list> +#include <thread> +#include <vector> +#include "test/cpp/qps/histogram.h" + +using std::list; +using std::thread; +using std::unique_ptr; +using std::vector; + +namespace grpc { +namespace testing { +static vector<string> get_hosts(const string& name) { + char* env = gpr_getenv(name.c_str()); + if (!env) return vector<string>(); + + vector<string> out; + char* p = env; + for (;;) { + char* comma = strchr(p, ','); + if (comma) { + out.emplace_back(p, comma); + p = comma + 1; + } else { + out.emplace_back(p); + gpr_free(env); + return out; + } + } +} + +ScenarioResult RunScenario(const ClientConfig& initial_client_config, + size_t num_clients, + const ServerConfig& server_config, + size_t num_servers) { + // ClientContext allocator (all are destroyed at scope exit) + list<ClientContext> contexts; + auto alloc_context = [&contexts]() { + contexts.emplace_back(); + return &contexts.back(); + }; + + // Get client, server lists + auto workers = get_hosts("QPS_WORKERS"); + ClientConfig client_config = initial_client_config; + + // TODO(ctiller): support running multiple configurations, and binpack + // client/server pairs + // to available workers + GPR_ASSERT(workers.size() >= num_clients + num_servers); + + // Trim to just what we need + workers.resize(num_clients + num_servers); + + // Start servers + struct ServerData { + unique_ptr<Worker::Stub> stub; + unique_ptr<ClientReaderWriter<ServerArgs, ServerStatus>> stream; + }; + vector<ServerData> servers; + for (size_t i = 0; i < num_servers; i++) { + ServerData sd; + sd.stub = std::move(Worker::NewStub( + CreateChannel(workers[i], InsecureCredentials(), ChannelArguments()))); + ServerArgs args; + *args.mutable_setup() = server_config; + sd.stream = std::move(sd.stub->RunServer(alloc_context())); + GPR_ASSERT(sd.stream->Write(args)); + ServerStatus init_status; + GPR_ASSERT(sd.stream->Read(&init_status)); + char* host; + char* driver_port; + char* cli_target; + gpr_split_host_port(workers[i].c_str(), &host, &driver_port); + gpr_join_host_port(&cli_target, host, init_status.port()); + client_config.add_server_targets(cli_target); + gpr_free(host); + gpr_free(driver_port); + gpr_free(cli_target); + + servers.push_back(std::move(sd)); + } + + // Start clients + struct ClientData { + unique_ptr<Worker::Stub> stub; + unique_ptr<ClientReaderWriter<ClientArgs, ClientStatus>> stream; + }; + vector<ClientData> clients; + for (size_t i = 0; i < num_clients; i++) { + ClientData cd; + cd.stub = std::move(Worker::NewStub(CreateChannel( + workers[i + num_servers], InsecureCredentials(), ChannelArguments()))); + ClientArgs args; + *args.mutable_setup() = client_config; + cd.stream = std::move(cd.stub->RunTest(alloc_context())); + GPR_ASSERT(cd.stream->Write(args)); + ClientStatus init_status; + GPR_ASSERT(cd.stream->Read(&init_status)); + + clients.push_back(std::move(cd)); + } + + // Let everything warmup + gpr_log(GPR_INFO, "Warming up"); + gpr_timespec start = gpr_now(); + gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(5))); + + // Start a run + gpr_log(GPR_INFO, "Starting"); + ServerArgs server_mark; + server_mark.mutable_mark(); + ClientArgs client_mark; + client_mark.mutable_mark(); + for (auto& server : servers) { + GPR_ASSERT(server.stream->Write(server_mark)); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Write(client_mark)); + } + ServerStatus server_status; + ClientStatus client_status; + for (auto& server : servers) { + GPR_ASSERT(server.stream->Read(&server_status)); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Read(&client_status)); + } + + // Wait some time + gpr_log(GPR_INFO, "Running"); + gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(15))); + + // Finish a run + ScenarioResult result; + gpr_log(GPR_INFO, "Finishing"); + for (auto& server : servers) { + GPR_ASSERT(server.stream->Write(server_mark)); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Write(client_mark)); + } + for (auto& server : servers) { + GPR_ASSERT(server.stream->Read(&server_status)); + const auto& stats = server_status.stats(); + result.server_resources.push_back(ResourceUsage{ + stats.time_elapsed(), stats.time_user(), stats.time_system()}); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Read(&client_status)); + const auto& stats = client_status.stats(); + result.latencies.MergeProto(stats.latencies()); + result.client_resources.push_back(ResourceUsage{ + stats.time_elapsed(), stats.time_user(), stats.time_system()}); + } + + for (auto& client : clients) { + GPR_ASSERT(client.stream->WritesDone()); + GPR_ASSERT(client.stream->Finish().IsOk()); + } + for (auto& server : servers) { + GPR_ASSERT(server.stream->WritesDone()); + GPR_ASSERT(server.stream->Finish().IsOk()); + } + return result; +} +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h new file mode 100644 index 0000000000..d87e80dc55 --- /dev/null +++ b/test/cpp/qps/driver.h @@ -0,0 +1,61 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_DRIVER_H +#define TEST_QPS_DRIVER_H + +#include "test/cpp/qps/histogram.h" +#include "test/cpp/qps/qpstest.pb.h" + +namespace grpc { +namespace testing { +struct ResourceUsage { + double wall_time; + double user_time; + double system_time; +}; + +struct ScenarioResult { + Histogram latencies; + std::vector<ResourceUsage> client_resources; + std::vector<ResourceUsage> server_resources; +}; + +ScenarioResult RunScenario(const grpc::testing::ClientConfig& client_config, + size_t num_clients, + const grpc::testing::ServerConfig& server_config, + size_t num_servers); +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h new file mode 100644 index 0000000000..7ba00e94c3 --- /dev/null +++ b/test/cpp/qps/histogram.h @@ -0,0 +1,85 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_HISTOGRAM_H +#define TEST_QPS_HISTOGRAM_H + +#include <grpc/support/histogram.h> +#include "test/cpp/qps/qpstest.pb.h" + +namespace grpc { +namespace testing { + +class Histogram { + public: + Histogram() : impl_(gpr_histogram_create(0.01, 60e9)) {} + ~Histogram() { + if (impl_) gpr_histogram_destroy(impl_); + } + Histogram(Histogram&& other) : impl_(other.impl_) { other.impl_ = nullptr; } + + void Merge(Histogram* h) { gpr_histogram_merge(impl_, h->impl_); } + void Add(double value) { gpr_histogram_add(impl_, value); } + double Percentile(double pctile) { + return gpr_histogram_percentile(impl_, pctile); + } + double Count() { return gpr_histogram_count(impl_); } + void Swap(Histogram* other) { std::swap(impl_, other->impl_); } + void FillProto(HistogramData* p) { + size_t n; + const auto* data = gpr_histogram_get_contents(impl_, &n); + for (size_t i = 0; i < n; i++) { + p->add_bucket(data[i]); + } + p->set_min_seen(gpr_histogram_minimum(impl_)); + p->set_max_seen(gpr_histogram_maximum(impl_)); + p->set_sum(gpr_histogram_sum(impl_)); + p->set_sum_of_squares(gpr_histogram_sum_of_squares(impl_)); + p->set_count(gpr_histogram_count(impl_)); + } + void MergeProto(const HistogramData& p) { + gpr_histogram_merge_contents(impl_, &*p.bucket().begin(), p.bucket_size(), + p.min_seen(), p.max_seen(), p.sum(), + p.sum_of_squares(), p.count()); + } + + private: + Histogram(const Histogram&); + Histogram& operator=(const Histogram&); + + gpr_histogram* impl_; +}; +} +} + +#endif /* TEST_QPS_HISTOGRAM_H */ diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc new file mode 100644 index 0000000000..bf51e7408e --- /dev/null +++ b/test/cpp/qps/qps_driver.cc @@ -0,0 +1,132 @@ +/* + * + * 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 <gflags/gflags.h> +#include <grpc/support/log.h> + +#include "test/cpp/qps/driver.h" +#include "test/cpp/qps/stats.h" + +DEFINE_int32(num_clients, 1, "Number of client binaries"); +DEFINE_int32(num_servers, 1, "Number of server binaries"); + +// Common config +DEFINE_bool(enable_ssl, false, "Use SSL"); + +// Server config +DEFINE_int32(server_threads, 1, "Number of server threads"); +DEFINE_string(server_type, "SYNCHRONOUS_SERVER", "Server type"); + +// Client config +DEFINE_int32(outstanding_rpcs_per_channel, 1, + "Number of outstanding rpcs per channel"); +DEFINE_int32(client_channels, 1, "Number of client channels"); +DEFINE_int32(payload_size, 1, "Payload size"); +DEFINE_string(client_type, "SYNCHRONOUS_CLIENT", "Client type"); +DEFINE_int32(async_client_threads, 1, "Async client threads"); + +using grpc::testing::ClientConfig; +using grpc::testing::ServerConfig; +using grpc::testing::ClientType; +using grpc::testing::ServerType; +using grpc::testing::ResourceUsage; +using grpc::testing::sum; + +// In some distros, gflags is in the namespace google, and in some others, +// in gflags. This hack is enabling us to find both. +namespace google {} +namespace gflags {} +using namespace google; +using namespace gflags; + +int main(int argc, char **argv) { + grpc_init(); + ParseCommandLineFlags(&argc, &argv, true); + + ClientType client_type; + ServerType server_type; + GPR_ASSERT(ClientType_Parse(FLAGS_client_type, &client_type)); + GPR_ASSERT(ServerType_Parse(FLAGS_server_type, &server_type)); + + ClientConfig client_config; + client_config.set_client_type(client_type); + client_config.set_enable_ssl(FLAGS_enable_ssl); + client_config.set_outstanding_rpcs_per_channel( + FLAGS_outstanding_rpcs_per_channel); + client_config.set_client_channels(FLAGS_client_channels); + client_config.set_payload_size(FLAGS_payload_size); + client_config.set_async_client_threads(FLAGS_async_client_threads); + + ServerConfig server_config; + server_config.set_server_type(server_type); + server_config.set_threads(FLAGS_server_threads); + server_config.set_enable_ssl(FLAGS_enable_ssl); + + auto result = RunScenario(client_config, FLAGS_num_clients, server_config, + FLAGS_num_servers); + + gpr_log(GPR_INFO, "QPS: %.1f", + result.latencies.Count() / + average(result.client_resources, + [](ResourceUsage u) { return u.wall_time; })); + + gpr_log(GPR_INFO, "Latencies (50/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f us", + result.latencies.Percentile(50) / 1000, + result.latencies.Percentile(95) / 1000, + result.latencies.Percentile(99) / 1000, + result.latencies.Percentile(99.9) / 1000); + + gpr_log(GPR_INFO, "Server system time: %.2f%%", + 100.0 * sum(result.server_resources, + [](ResourceUsage u) { return u.system_time; }) / + sum(result.server_resources, + [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Server user time: %.2f%%", + 100.0 * sum(result.server_resources, + [](ResourceUsage u) { return u.user_time; }) / + sum(result.server_resources, + [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Client system time: %.2f%%", + 100.0 * sum(result.client_resources, + [](ResourceUsage u) { return u.system_time; }) / + sum(result.client_resources, + [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Client user time: %.2f%%", + 100.0 * sum(result.client_resources, + [](ResourceUsage u) { return u.user_time; }) / + sum(result.client_resources, + [](ResourceUsage u) { return u.wall_time; })); + + grpc_shutdown(); + return 0; +} diff --git a/test/cpp/qps/qpstest.proto b/test/cpp/qps/qpstest.proto index 68ec6149f5..6a7170bf58 100644 --- a/test/cpp/qps/qpstest.proto +++ b/test/cpp/qps/qpstest.proto @@ -51,17 +51,14 @@ message StatsRequest { } message ServerStats { - // wall clock time for timestamp - required double time_now = 1; + // wall clock time + required double time_elapsed = 1; // user time used by the server process and threads required double time_user = 2; // server time used by the server process and all threads required double time_system = 3; - - // RPC count so far - optional int32 num_rpcs = 4; } message Payload { @@ -71,31 +68,75 @@ message Payload { optional bytes body = 2; } -message Latencies { - required double l_50 = 1; - required double l_90 = 2; - required double l_99 = 3; - required double l_999 = 4; +message HistogramData { + repeated uint32 bucket = 1; + required double min_seen = 2; + required double max_seen = 3; + required double sum = 4; + required double sum_of_squares = 5; + required double count = 6; +} + +enum ClientType { + SYNCHRONOUS_CLIENT = 1; + ASYNC_CLIENT = 2; +} + +enum ServerType { + SYNCHRONOUS_SERVER = 1; + ASYNC_SERVER = 2; +} + +message ClientConfig { + repeated string server_targets = 1; + required ClientType client_type = 2; + required bool enable_ssl = 3; + required int32 outstanding_rpcs_per_channel = 4; + required int32 client_channels = 5; + required int32 payload_size = 6; + // only for async client: + optional int32 async_client_threads = 7; } -message StartArgs { - required string server_host = 1; - required int32 server_port = 2; - optional bool enable_ssl = 3 [default = false]; - optional int32 client_threads = 4 [default = 1]; - optional int32 client_channels = 5 [default = -1]; - optional int32 num_rpcs = 6 [default = 1]; - optional int32 payload_size = 7 [default = 1]; +// Request current stats +message Mark {} + +message ClientArgs { + oneof argtype { + ClientConfig setup = 1; + Mark mark = 2; + } } -message StartResult { - required Latencies latencies = 1; - required int32 num_rpcs = 2; +message ClientStats { + required HistogramData latencies = 1; required double time_elapsed = 3; required double time_user = 4; required double time_system = 5; } +message ClientStatus { + optional ClientStats stats = 1; +} + +message ServerConfig { + required ServerType server_type = 1; + required int32 threads = 2; + required bool enable_ssl = 3; +} + +message ServerArgs { + oneof argtype { + ServerConfig setup = 1; + Mark mark = 2; + } +} + +message ServerStatus { + optional ServerStats stats = 1; + required int32 port = 2; +} + message SimpleRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, server randomly chooses one from other formats. @@ -153,12 +194,6 @@ message StreamingOutputCallResponse { } service TestService { - // Start test with specified workload - rpc StartTest(StartArgs) returns (Latencies); - - // Collect stats from server, ignore request content - rpc CollectServerStats(StatsRequest) returns (ServerStats); - // One request followed by one response. // The server returns the client payload as-is. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); @@ -186,3 +221,10 @@ service TestService { rpc HalfDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); } + +service Worker { + // Start test with specified workload + rpc RunTest(stream ClientArgs) returns (stream ClientStatus); + // Start test with specified workload + rpc RunServer(stream ServerArgs) returns (stream ServerStatus); +} diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server.cc index be27c12b30..005f0f9c5e 100644 --- a/test/cpp/qps/server.cc +++ b/test/cpp/qps/server.cc @@ -45,6 +45,7 @@ #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> #include <grpc++/status.h> #include "src/cpp/server/thread_pool.h" #include "test/core/util/grpc_profiler.h" @@ -136,7 +137,7 @@ static void RunServer() { SimpleResponse response; ServerBuilder builder; - builder.AddPort(server_address); + builder.AddPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr<ThreadPool> pool(new ThreadPool(FLAGS_server_threads)); diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h new file mode 100644 index 0000000000..ef71cb94d0 --- /dev/null +++ b/test/cpp/qps/server.h @@ -0,0 +1,84 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_SERVER_H +#define TEST_QPS_SERVER_H + +#include "test/cpp/qps/timer.h" +#include "test/cpp/qps/qpstest.pb.h" + +namespace grpc { +namespace testing { + +class Server { + public: + Server() : timer_(new Timer) {} + virtual ~Server() {} + + ServerStats Mark() { + std::unique_ptr<Timer> timer(new Timer); + timer.swap(timer_); + + auto timer_result = timer->Mark(); + + ServerStats stats; + stats.set_time_elapsed(timer_result.wall); + stats.set_time_system(timer_result.system); + stats.set_time_user(timer_result.user); + return stats; + } + + static bool SetPayload(PayloadType type, int size, Payload* payload) { + PayloadType response_type = type; + // TODO(yangg): Support UNCOMPRESSABLE payload. + if (type != PayloadType::COMPRESSABLE) { + return false; + } + payload->set_type(response_type); + std::unique_ptr<char[]> body(new char[size]()); + payload->set_body(body.get(), size); + return true; + } + + private: + std::unique_ptr<Timer> timer_; +}; + +std::unique_ptr<Server> CreateSynchronousServer(const ServerConfig& config, + int port); +std::unique_ptr<Server> CreateAsyncServer(const ServerConfig& config, int port); + +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc new file mode 100644 index 0000000000..19778e5a7c --- /dev/null +++ b/test/cpp/qps/server_async.cc @@ -0,0 +1,212 @@ +/* + * + * 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 <forward_list> +#include <functional> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/signal.h> +#include <thread> + +#include <gflags/gflags.h> +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc++/async_unary_call.h> +#include <grpc++/config.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> +#include <grpc++/status.h> +#include <gtest/gtest.h> +#include "src/cpp/server/thread_pool.h" +#include "test/core/util/grpc_profiler.h" +#include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/server.h" + +#include <grpc/grpc.h> +#include <grpc/support/log.h> + +namespace grpc { +namespace testing { + +class AsyncQpsServerTest : public Server { + public: + AsyncQpsServerTest(const ServerConfig &config, int port) + : srv_cq_(), async_service_(&srv_cq_), server_(nullptr) { + char *server_address = NULL; + gpr_join_host_port(&server_address, "::", port); + + ServerBuilder builder; + builder.AddPort(server_address, InsecureServerCredentials()); + gpr_free(server_address); + + builder.RegisterAsyncService(&async_service_); + + server_ = builder.BuildAndStart(); + + using namespace std::placeholders; + request_unary_ = std::bind(&TestService::AsyncService::RequestUnaryCall, + &async_service_, _1, _2, _3, &srv_cq_, _4); + for (int i = 0; i < 100; i++) { + contexts_.push_front( + new ServerRpcContextUnaryImpl<SimpleRequest, SimpleResponse>( + request_unary_, UnaryCall)); + } + 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; + void *got_tag; + while (srv_cq_.Next(&got_tag, &ok)) { + if (ok) { + ServerRpcContext *ctx = detag(got_tag); + // The tag is a pointer to an RPC context to invoke + if (ctx->RunNextState() == false) { + // this RPC context is done, so refresh it + ctx->Reset(); + } + } + } + return; + })); + } + } + ~AsyncQpsServerTest() { + server_->Shutdown(); + srv_cq_.Shutdown(); + for (auto &thr : threads_) { + thr.join(); + } + while (!contexts_.empty()) { + delete contexts_.front(); + contexts_.pop_front(); + } + } + + private: + class ServerRpcContext { + public: + ServerRpcContext() {} + virtual ~ServerRpcContext(){}; + virtual bool RunNextState() = 0; // do next state, return false if all done + virtual void Reset() = 0; // start this back at a clean state + }; + static void *tag(ServerRpcContext *func) { + return reinterpret_cast<void *>(func); + } + static ServerRpcContext *detag(void *tag) { + return reinterpret_cast<ServerRpcContext *>(tag); + } + + template <class RequestType, class ResponseType> + class ServerRpcContextUnaryImpl : public ServerRpcContext { + public: + ServerRpcContextUnaryImpl( + std::function<void(ServerContext *, RequestType *, + grpc::ServerAsyncResponseWriter<ResponseType> *, + void *)> request_method, + std::function<grpc::Status(const RequestType *, ResponseType *)> + invoke_method) + : next_state_(&ServerRpcContextUnaryImpl::invoker), + request_method_(request_method), + invoke_method_(invoke_method), + response_writer_(&srv_ctx_) { + request_method_(&srv_ctx_, &req_, &response_writer_, + AsyncQpsServerTest::tag(this)); + } + ~ServerRpcContextUnaryImpl() GRPC_OVERRIDE {} + bool RunNextState() GRPC_OVERRIDE { return (this->*next_state_)(); } + void Reset() GRPC_OVERRIDE { + srv_ctx_ = ServerContext(); + req_ = RequestType(); + response_writer_ = + grpc::ServerAsyncResponseWriter<ResponseType>(&srv_ctx_); + + // Then request the method + next_state_ = &ServerRpcContextUnaryImpl::invoker; + request_method_(&srv_ctx_, &req_, &response_writer_, + AsyncQpsServerTest::tag(this)); + } + + private: + bool finisher() { return false; } + bool invoker() { + ResponseType response; + + // Call the RPC processing function + grpc::Status status = invoke_method_(&req_, &response); + + // Have the response writer work and invoke on_finish when done + next_state_ = &ServerRpcContextUnaryImpl::finisher; + response_writer_.Finish(response, status, AsyncQpsServerTest::tag(this)); + return true; + } + ServerContext srv_ctx_; + RequestType req_; + bool (ServerRpcContextUnaryImpl::*next_state_)(); + std::function<void(ServerContext *, RequestType *, + grpc::ServerAsyncResponseWriter<ResponseType> *, void *)> + request_method_; + std::function<grpc::Status(const RequestType *, ResponseType *)> + invoke_method_; + grpc::ServerAsyncResponseWriter<ResponseType> response_writer_; + }; + + static Status UnaryCall(const SimpleRequest *request, + SimpleResponse *response) { + if (request->has_response_size() && request->response_size() > 0) { + if (!SetPayload(request->response_type(), request->response_size(), + response->mutable_payload())) { + return Status(grpc::StatusCode::INTERNAL, "Error creating payload."); + } + } + return Status::OK; + } + CompletionQueue srv_cq_; + TestService::AsyncService async_service_; + std::vector<std::thread> threads_; + std::unique_ptr<grpc::Server> server_; + std::function<void(ServerContext *, SimpleRequest *, + grpc::ServerAsyncResponseWriter<SimpleResponse> *, void *)> + request_unary_; + std::forward_list<ServerRpcContext *> contexts_; +}; + +std::unique_ptr<Server> CreateAsyncServer(const ServerConfig &config, + int port) { + return std::unique_ptr<Server>(new AsyncQpsServerTest(config, port)); +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc new file mode 100644 index 0000000000..5c6541989c --- /dev/null +++ b/test/cpp/qps/server_sync.cc @@ -0,0 +1,108 @@ +/* + * + * 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/signal.h> +#include <thread> + +#include <unistd.h> + +#include <gflags/gflags.h> +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc++/config.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> +#include <grpc++/status.h> +#include <grpc++/stream.h> +#include "src/cpp/server/thread_pool.h" +#include "test/core/util/grpc_profiler.h" +#include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/server.h" +#include "test/cpp/qps/timer.h" + +#include <grpc/grpc.h> +#include <grpc/support/log.h> + +namespace grpc { +namespace testing { + +class TestServiceImpl GRPC_FINAL : public TestService::Service { + public: + Status UnaryCall(ServerContext* context, const SimpleRequest* request, + SimpleResponse* response) GRPC_OVERRIDE { + if (request->has_response_size() && request->response_size() > 0) { + if (!Server::SetPayload(request->response_type(), + request->response_size(), + response->mutable_payload())) { + return Status(grpc::StatusCode::INTERNAL, "Error creating payload."); + } + } + return Status::OK; + } +}; + +class SynchronousServer GRPC_FINAL : public grpc::testing::Server { + public: + SynchronousServer(const ServerConfig& config, int port) + : thread_pool_(config.threads()), impl_(MakeImpl(port)) {} + + private: + std::unique_ptr<grpc::Server> MakeImpl(int port) { + ServerBuilder builder; + + char* server_address = NULL; + gpr_join_host_port(&server_address, "::", port); + builder.AddPort(server_address, InsecureServerCredentials()); + gpr_free(server_address); + + builder.RegisterService(&service_); + + builder.SetThreadPool(&thread_pool_); + + return builder.BuildAndStart(); + } + + TestServiceImpl service_; + ThreadPool thread_pool_; + std::unique_ptr<grpc::Server> impl_; +}; + +std::unique_ptr<grpc::testing::Server> CreateSynchronousServer( + const ServerConfig& config, int port) { + return std::unique_ptr<Server>(new SynchronousServer(config, port)); +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh new file mode 100755 index 0000000000..2f60b4e49d --- /dev/null +++ b/test/cpp/qps/single_run_localhost.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# performs a single qps run with one client and one server + +set -ex + +cd $(dirname $0)/../../.. + +killall qps_worker || true + +config=opt + +NUMCPUS=`python2.7 -c 'import multiprocessing; print multiprocessing.cpu_count()'` + +make CONFIG=$config qps_worker qps_driver -j$NUMCPUS + +bins/$config/qps_worker -driver_port 10000 -server_port 10001 & +PID1=$! +bins/$config/qps_worker -driver_port 10010 -server_port 10011 & +PID2=$! + +export QPS_WORKERS="localhost:10000,localhost:10010" + +bins/$config/qps_driver $* + +kill -2 $PID1 $PID2 +wait + diff --git a/test/cpp/qps/stats.h b/test/cpp/qps/stats.h new file mode 100644 index 0000000000..ca59390ad7 --- /dev/null +++ b/test/cpp/qps/stats.h @@ -0,0 +1,60 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_STATS_UTILS_H +#define TEST_QPS_STATS_UTILS_H + +#include "test/cpp/qps/histogram.h" +#include <string> + +namespace grpc { +namespace testing { + +template <class T, class F> +double sum(const T& container, F functor) { + double r = 0; + for (auto v : container) { + r += functor(v); + } + return r; +} + +template <class T, class F> +double average(const T& container, F functor) { + return sum(container, functor) / container.size(); +} + +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/timer.cc b/test/cpp/qps/timer.cc new file mode 100644 index 0000000000..3c1342041c --- /dev/null +++ b/test/cpp/qps/timer.cc @@ -0,0 +1,71 @@ +/* + * + * 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 "test/cpp/qps/timer.h" + +#include <sys/time.h> +#include <sys/resource.h> +#include <grpc/support/time.h> + +Timer::Timer() : start_(Sample()) {} + +double Timer::Now() { + auto ts = gpr_now(); + return ts.tv_sec + 1e-9 * ts.tv_nsec; +} + +static double time_double(struct timeval* tv) { + return tv->tv_sec + 1e-6 * tv->tv_usec; +} + +Timer::Result Timer::Sample() { + struct rusage usage; + struct timeval tv; + gettimeofday(&tv, nullptr); + getrusage(RUSAGE_SELF, &usage); + + Result r; + r.wall = time_double(&tv); + r.user = time_double(&usage.ru_utime); + r.system = time_double(&usage.ru_stime); + return r; +} + +Timer::Result Timer::Mark() { + Result s = Sample(); + Result r; + r.wall = s.wall - start_.wall; + r.user = s.user - start_.user; + r.system = s.system - start_.system; + return r; +} diff --git a/test/cpp/qps/timer.h b/test/cpp/qps/timer.h new file mode 100644 index 0000000000..30dbd7e7d5 --- /dev/null +++ b/test/cpp/qps/timer.h @@ -0,0 +1,57 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_TIMER_H +#define TEST_QPS_TIMER_H + +class Timer { + public: + Timer(); + + struct Result { + double wall; + double user; + double system; + }; + + Result Mark(); + + static double Now(); + + private: + static Result Sample(); + + const Result start_; +}; + +#endif // TEST_QPS_TIMER_H diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc new file mode 100644 index 0000000000..faabfd1147 --- /dev/null +++ b/test/cpp/qps/worker.cc @@ -0,0 +1,236 @@ +/* + * + * 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 <cassert> +#include <memory> +#include <mutex> +#include <string> +#include <thread> +#include <vector> +#include <sstream> + +#include <sys/signal.h> + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/histogram.h> +#include <grpc/support/log.h> +#include <grpc/support/host_port.h> +#include <gflags/gflags.h> +#include <grpc++/client_context.h> +#include <grpc++/status.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include <grpc++/server_credentials.h> +#include <grpc++/stream.h> +#include "test/core/util/grpc_profiler.h" +#include "test/cpp/util/create_test_channel.h" +#include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/client.h" +#include "test/cpp/qps/server.h" + +DEFINE_int32(driver_port, 0, "Driver server port."); +DEFINE_int32(server_port, 0, "Spawned server port."); + +// In some distros, gflags is in the namespace google, and in some others, +// in gflags. This hack is enabling us to find both. +namespace google {} +namespace gflags {} +using namespace google; +using namespace gflags; + +static bool got_sigint = false; + +namespace grpc { +namespace testing { + +std::unique_ptr<Client> CreateClient(const ClientConfig& config) { + switch (config.client_type()) { + case ClientType::SYNCHRONOUS_CLIENT: + return CreateSynchronousClient(config); + case ClientType::ASYNC_CLIENT: + return CreateAsyncClient(config); + } + abort(); +} + +std::unique_ptr<Server> CreateServer(const ServerConfig& config) { + switch (config.server_type()) { + case ServerType::SYNCHRONOUS_SERVER: + return CreateSynchronousServer(config, FLAGS_server_port); + case ServerType::ASYNC_SERVER: + return CreateAsyncServer(config, FLAGS_server_port); + } + abort(); +} + +class WorkerImpl GRPC_FINAL : public Worker::Service { + public: + WorkerImpl() : acquired_(false) {} + + Status RunTest(ServerContext* ctx, + ServerReaderWriter<ClientStatus, ClientArgs>* stream) + GRPC_OVERRIDE { + InstanceGuard g(this); + if (!g.Acquired()) { + return Status(RESOURCE_EXHAUSTED); + } + + ClientArgs args; + if (!stream->Read(&args)) { + return Status(INVALID_ARGUMENT); + } + if (!args.has_setup()) { + return Status(INVALID_ARGUMENT); + } + auto client = CreateClient(args.setup()); + if (!client) { + return Status(INVALID_ARGUMENT); + } + ClientStatus status; + if (!stream->Write(status)) { + return Status(UNKNOWN); + } + while (stream->Read(&args)) { + if (!args.has_mark()) { + return Status(INVALID_ARGUMENT); + } + *status.mutable_stats() = client->Mark(); + stream->Write(status); + } + + return Status::OK; + } + + Status RunServer(ServerContext* ctx, + ServerReaderWriter<ServerStatus, ServerArgs>* stream) + GRPC_OVERRIDE { + InstanceGuard g(this); + if (!g.Acquired()) { + return Status(RESOURCE_EXHAUSTED); + } + + ServerArgs args; + if (!stream->Read(&args)) { + return Status(INVALID_ARGUMENT); + } + if (!args.has_setup()) { + return Status(INVALID_ARGUMENT); + } + auto server = CreateServer(args.setup()); + if (!server) { + return Status(INVALID_ARGUMENT); + } + ServerStatus status; + status.set_port(FLAGS_server_port); + if (!stream->Write(status)) { + return Status(UNKNOWN); + } + while (stream->Read(&args)) { + if (!args.has_mark()) { + return Status(INVALID_ARGUMENT); + } + *status.mutable_stats() = server->Mark(); + stream->Write(status); + } + + return Status::OK; + } + + private: + // Protect against multiple clients using this worker at once. + class InstanceGuard { + public: + InstanceGuard(WorkerImpl* impl) + : impl_(impl), acquired_(impl->TryAcquireInstance()) {} + ~InstanceGuard() { + if (acquired_) { + impl_->ReleaseInstance(); + } + } + + bool Acquired() const { return acquired_; } + + private: + WorkerImpl* const impl_; + const bool acquired_; + }; + + bool TryAcquireInstance() { + std::lock_guard<std::mutex> g(mu_); + if (acquired_) return false; + acquired_ = true; + return true; + } + + void ReleaseInstance() { + std::lock_guard<std::mutex> g(mu_); + GPR_ASSERT(acquired_); + acquired_ = false; + } + + std::mutex mu_; + bool acquired_; +}; + +static void RunServer() { + char* server_address = NULL; + gpr_join_host_port(&server_address, "::", FLAGS_driver_port); + + WorkerImpl service; + + ServerBuilder builder; + builder.AddPort(server_address, InsecureServerCredentials()); + builder.RegisterService(&service); + + gpr_free(server_address); + + auto server = builder.BuildAndStart(); + + while (!got_sigint) { + std::this_thread::sleep_for(std::chrono::seconds(5)); + } +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc_init(); + ParseCommandLineFlags(&argc, &argv, true); + + grpc::testing::RunServer(); + + grpc_shutdown(); + return 0; +} diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc index 745496f463..d3b84b2965 100644 --- a/test/cpp/util/create_test_channel.cc +++ b/test/cpp/util/create_test_channel.cc @@ -61,12 +61,10 @@ std::shared_ptr<ChannelInterface> CreateTestChannel( const std::unique_ptr<Credentials>& creds) { ChannelArguments channel_args; if (enable_ssl) { - const char* roots_certs = - use_prod_roots ? "" : test_root_cert; + const char* roots_certs = use_prod_roots ? "" : test_root_cert; SslCredentialsOptions ssl_opts = {roots_certs, "", ""}; - std::unique_ptr<Credentials> channel_creds = - CredentialsFactory::SslCredentials(ssl_opts); + std::unique_ptr<Credentials> channel_creds = SslCredentials(ssl_opts); if (!server.empty() && !override_hostname.empty()) { channel_args.SetSslTargetNameOverride(override_hostname); @@ -75,11 +73,11 @@ std::shared_ptr<ChannelInterface> CreateTestChannel( server.empty() ? override_hostname : server; if (creds.get()) { channel_creds = - CredentialsFactory::CompositeCredentials(creds, channel_creds); + CompositeCredentials(creds, channel_creds); } return CreateChannel(connect_to, channel_creds, channel_args); } else { - return CreateChannelDeprecated(server, channel_args); + return CreateChannel(server, InsecureCredentials(), channel_args); } } diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h index 3476b8354b..5c298ce850 100644 --- a/test/cpp/util/create_test_channel.h +++ b/test/cpp/util/create_test_channel.h @@ -31,8 +31,8 @@ * */ -#ifndef __GRPCPP_TEST_UTIL_CREATE_TEST_CHANNEL_H_ -#define __GRPCPP_TEST_UTIL_CREATE_TEST_CHANNEL_H_ +#ifndef GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H +#define GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H #include <memory> @@ -56,4 +56,4 @@ std::shared_ptr<ChannelInterface> CreateTestChannel( } // namespace grpc -#endif // __GRPCPP_TEST_UTIL_CREATE_TEST_CHANNEL_H_ +#endif // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H |