diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/compiler/python_plugin_test.py | 2 | ||||
-rw-r--r-- | test/core/bad_client/bad_client.c | 136 | ||||
-rw-r--r-- | test/core/bad_client/bad_client.h | 52 | ||||
-rwxr-xr-x | test/core/bad_client/gen_build_json.py | 79 | ||||
-rw-r--r-- | test/core/bad_client/tests/connection_prefix.c | 79 | ||||
-rw-r--r-- | test/core/support/cmdline_test.c | 23 | ||||
-rw-r--r-- | test/cpp/end2end/server_crash_test.cc | 36 | ||||
-rw-r--r-- | test/cpp/interop/interop_client.cc | 4 | ||||
-rw-r--r-- | test/cpp/qps/async_streaming_ping_pong_test.cc | 10 | ||||
-rw-r--r-- | test/cpp/qps/async_unary_ping_pong_test.cc | 11 | ||||
-rw-r--r-- | test/cpp/qps/qps_driver.cc | 27 | ||||
-rw-r--r-- | test/cpp/qps/qps_test.cc | 9 | ||||
-rw-r--r-- | test/cpp/qps/report.cc | 50 | ||||
-rw-r--r-- | test/cpp/qps/report.h | 77 | ||||
-rw-r--r-- | test/cpp/qps/sync_streaming_ping_pong_test.cc | 10 | ||||
-rw-r--r-- | test/cpp/qps/sync_unary_ping_pong_test.cc | 9 | ||||
-rw-r--r-- | test/cpp/util/benchmark_config.cc | 69 | ||||
-rw-r--r-- | test/cpp/util/benchmark_config.h | 57 |
18 files changed, 684 insertions, 56 deletions
diff --git a/test/compiler/python_plugin_test.py b/test/compiler/python_plugin_test.py index ad3bebac30..367effdb1a 100644 --- a/test/compiler/python_plugin_test.py +++ b/test/compiler/python_plugin_test.py @@ -520,4 +520,4 @@ class PythonPluginTest(unittest.TestCase): if __name__ == '__main__': os.chdir(os.path.dirname(sys.argv[0])) - unittest.main() + unittest.main(verbosity=2) diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c new file mode 100644 index 0000000000..c3725b5909 --- /dev/null +++ b/test/core/bad_client/bad_client.c @@ -0,0 +1,136 @@ +/* + * + * 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/bad_client/bad_client.h" + +#include "src/core/channel/channel_stack.h" +#include "src/core/channel/http_server_filter.h" +#include "src/core/iomgr/endpoint_pair.h" +#include "src/core/surface/completion_queue.h" +#include "src/core/surface/server.h" +#include "src/core/transport/chttp2_transport.h" + +#include <grpc/support/sync.h> +#include <grpc/support/thd.h> + +typedef struct { + grpc_server *server; + grpc_completion_queue *cq; + grpc_bad_client_server_side_validator validator; + gpr_event done_thd; + gpr_event done_write; +} thd_args; + +static void thd_func(void *arg) { + thd_args *a = arg; + a->validator(a->server, a->cq); + gpr_event_set(&a->done_thd, (void *)1); +} + +static void done_write(void *arg, grpc_endpoint_cb_status status) { + thd_args *a = arg; + gpr_event_set(&a->done_write, (void *)1); +} + +static grpc_transport_setup_result server_setup_transport( + void *ts, grpc_transport *transport, grpc_mdctx *mdctx) { + thd_args *a = ts; + static grpc_channel_filter const *extra_filters[] = { + &grpc_http_server_filter}; + return grpc_server_setup_transport(a->server, transport, extra_filters, + GPR_ARRAY_SIZE(extra_filters), mdctx); +} + +void grpc_run_bad_client_test(const char *name, const char *client_payload, + size_t client_payload_length, + grpc_bad_client_server_side_validator validator) { + grpc_endpoint_pair sfd; + thd_args a; + gpr_thd_id id; + gpr_slice slice = + gpr_slice_from_copied_buffer(client_payload, client_payload_length); + + /* Add a debug log */ + gpr_log(GPR_INFO, "TEST: %s", name); + + /* Init grpc */ + grpc_init(); + + /* Create endpoints */ + sfd = grpc_iomgr_create_endpoint_pair(65536); + + /* Create server, completion events */ + a.server = grpc_server_create_from_filters(NULL, 0, NULL); + a.cq = grpc_completion_queue_create(); + gpr_event_init(&a.done_thd); + gpr_event_init(&a.done_write); + a.validator = validator; + grpc_server_register_completion_queue(a.server, a.cq); + grpc_server_start(a.server); + grpc_create_chttp2_transport(server_setup_transport, &a, NULL, sfd.server, + NULL, 0, grpc_mdctx_create(), 0); + + /* Bind everything into the same pollset */ + grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(a.cq)); + grpc_endpoint_add_to_pollset(sfd.server, grpc_cq_pollset(a.cq)); + + /* Check a ground truth */ + GPR_ASSERT(grpc_server_has_open_connections(a.server)); + + /* Start validator */ + gpr_thd_new(&id, thd_func, &a, NULL); + + /* Write data */ + switch (grpc_endpoint_write(sfd.client, &slice, 1, done_write, &a)) { + case GRPC_ENDPOINT_WRITE_DONE: + done_write(&a, 1); + break; + case GRPC_ENDPOINT_WRITE_PENDING: + break; + case GRPC_ENDPOINT_WRITE_ERROR: + done_write(&a, 0); + break; + } + + /* Await completion */ + GPR_ASSERT( + gpr_event_wait(&a.done_write, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); + GPR_ASSERT(gpr_event_wait(&a.done_thd, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); + + /* Shutdown */ + grpc_endpoint_destroy(sfd.client); + grpc_server_destroy(a.server); + grpc_completion_queue_destroy(a.cq); + + grpc_shutdown(); +} diff --git a/test/core/bad_client/bad_client.h b/test/core/bad_client/bad_client.h new file mode 100644 index 0000000000..4834e86cce --- /dev/null +++ b/test/core/bad_client/bad_client.h @@ -0,0 +1,52 @@ +/* + * + * 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 GRPC_TEST_CORE_BAD_CLIENT_BAD_CLIENT_H +#define GRPC_TEST_CORE_BAD_CLIENT_BAD_CLIENT_H + +#include <grpc/grpc.h> +#include "test/core/util/test_config.h" + +typedef void (*grpc_bad_client_server_side_validator)( + grpc_server *server, grpc_completion_queue *cq); + +/* Test runner. + + Create a server, and send client_payload to it as bytes from a client. + Execute validator in a separate thread to assert that the bytes are + handled as expected. */ +void grpc_run_bad_client_test(const char *name, const char *client_payload, + size_t client_payload_length, + grpc_bad_client_server_side_validator validator); + +#endif /* GRPC_TEST_CORE_BAD_CLIENT_BAD_CLIENT_H */ diff --git a/test/core/bad_client/gen_build_json.py b/test/core/bad_client/gen_build_json.py new file mode 100755 index 0000000000..67969a1a12 --- /dev/null +++ b/test/core/bad_client/gen_build_json.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# 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. + + +"""Generates the appropriate build.json data for all the end2end tests.""" + + +import simplejson +import collections + +TestOptions = collections.namedtuple('TestOptions', 'flaky') +default_test_options = TestOptions(False) + +# maps test names to options +BAD_CLIENT_TESTS = { + 'connection_prefix': default_test_options, +} + +def main(): + json = { + '#': 'generated with test/bad_client/gen_build_json.py', + 'libs': [ + { + 'name': 'bad_client_test', + 'build': 'private', + 'language': 'c', + 'src': [ + 'test/core/bad_client/bad_client.c' + ] + }], + 'targets': [ + { + 'name': '%s_bad_client_test' % t, + 'build': 'test', + 'language': 'c', + 'secure': 'no', + 'src': ['test/core/bad_client/tests/%s.c' % t], + 'flaky': 'invoke_large_request' in t, + 'deps': [ + 'bad_client_test', + 'grpc_test_util_unsecure', + 'grpc_unsecure', + 'gpr_test_util', + 'gpr' + ] + } + for t in sorted(BAD_CLIENT_TESTS.keys())]} + print simplejson.dumps(json, sort_keys=True, indent=2 * ' ') + + +if __name__ == '__main__': + main() diff --git a/test/core/bad_client/tests/connection_prefix.c b/test/core/bad_client/tests/connection_prefix.c new file mode 100644 index 0000000000..e8bf935710 --- /dev/null +++ b/test/core/bad_client/tests/connection_prefix.c @@ -0,0 +1,79 @@ +/* + * + * 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/bad_client/bad_client.h" +#include "src/core/surface/server.h" + +static void verifier(grpc_server *server, grpc_completion_queue *cq) { + while (grpc_server_has_open_connections(server)) { + GPR_ASSERT(grpc_completion_queue_next( + cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20)).type == + GRPC_QUEUE_TIMEOUT); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + grpc_run_bad_client_test("conpfx_1", "X", 1, verifier); + grpc_run_bad_client_test("conpfx_2", "PX", 2, verifier); + grpc_run_bad_client_test("conpfx_3", "PRX", 3, verifier); + grpc_run_bad_client_test("conpfx_4", "PRIX", 4, verifier); + grpc_run_bad_client_test("conpfx_5", "PRI X", 5, verifier); + grpc_run_bad_client_test("conpfx_6", "PRI *X", 6, verifier); + grpc_run_bad_client_test("conpfx_7", "PRI * X", 7, verifier); + grpc_run_bad_client_test("conpfx_8", "PRI * HX", 8, verifier); + grpc_run_bad_client_test("conpfx_9", "PRI * HTX", 9, verifier); + grpc_run_bad_client_test("conpfx_10", "PRI * HTTX", 10, verifier); + grpc_run_bad_client_test("conpfx_11", "PRI * HTTPX", 11, verifier); + grpc_run_bad_client_test("conpfx_12", "PRI * HTTP/X", 12, verifier); + grpc_run_bad_client_test("conpfx_13", "PRI * HTTP/2X", 13, verifier); + grpc_run_bad_client_test("conpfx_14", "PRI * HTTP/2.X", 14, verifier); + grpc_run_bad_client_test("conpfx_15", "PRI * HTTP/2.0X", 15, verifier); + grpc_run_bad_client_test("conpfx_16", "PRI * HTTP/2.0\rX", 16, verifier); + grpc_run_bad_client_test("conpfx_17", "PRI * HTTP/2.0\r\nX", 17, verifier); + grpc_run_bad_client_test("conpfx_18", "PRI * HTTP/2.0\r\n\rX", 18, verifier); + grpc_run_bad_client_test("conpfx_19", "PRI * HTTP/2.0\r\n\r\nX", 19, + verifier); + grpc_run_bad_client_test("conpfx_20", "PRI * HTTP/2.0\r\n\r\nSX", 20, + verifier); + grpc_run_bad_client_test("conpfx_21", "PRI * HTTP/2.0\r\n\r\nSMX", 21, + verifier); + grpc_run_bad_client_test("conpfx_22", "PRI * HTTP/2.0\r\n\r\nSM\rX", 22, + verifier); + grpc_run_bad_client_test("conpfx_23", "PRI * HTTP/2.0\r\n\r\nSM\r\nX", 23, + verifier); + grpc_run_bad_client_test("conpfx_24", "PRI * HTTP/2.0\r\n\r\nSM\r\n\rX", 24, + verifier); + return 0; +} diff --git a/test/core/support/cmdline_test.c b/test/core/support/cmdline_test.c index a7767ace5e..26153b192c 100644 --- a/test/core/support/cmdline_test.c +++ b/test/core/support/cmdline_test.c @@ -35,6 +35,7 @@ #include <string.h> +#include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/useful.h> #include "test/core/util/test_config.h" @@ -272,6 +273,27 @@ static void test_many(void) { gpr_cmdline_destroy(cl); } +static void test_usage(void) { + gpr_cmdline *cl; + char *usage; + + char *str = NULL; + int x = 0; + int flag = 2; + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + + usage = gpr_cmdline_usage_string(cl, "test"); + GPR_ASSERT(0 == strcmp(usage, + "Usage: test [--str=string] [--x=int] [--flag|--no-flag]\n")); + gpr_free(usage); + + gpr_cmdline_destroy(cl); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_simple_int(); @@ -289,5 +311,6 @@ int main(int argc, char **argv) { test_flag_val_true(); test_flag_val_false(); test_many(); + test_usage(); return 0; } diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc index 11d73aec7d..3fdae9bc07 100644 --- a/test/cpp/end2end/server_crash_test.cc +++ b/test/cpp/end2end/server_crash_test.cc @@ -69,10 +69,15 @@ namespace testing { namespace { -class ServiceImpl GRPC_FINAL : public ::grpc::cpp::test::util::TestService::Service { +class ServiceImpl GRPC_FINAL + : public ::grpc::cpp::test::util::TestService::Service { + public: + ServiceImpl() : bidi_stream_count_(0), response_stream_count_(0) {} + Status BidiStream(ServerContext* context, ServerReaderWriter<EchoResponse, EchoRequest>* stream) GRPC_OVERRIDE { + bidi_stream_count_++; EchoRequest request; EchoResponse response; while (stream->Read(&request)) { @@ -87,6 +92,7 @@ class ServiceImpl GRPC_FINAL : public ::grpc::cpp::test::util::TestService::Serv Status ResponseStream(ServerContext* context, const EchoRequest* request, ServerWriter<EchoResponse>* writer) GRPC_OVERRIDE { EchoResponse response; + response_stream_count_++; for (int i = 0;; i++) { std::ostringstream msg; msg << "Hello " << i; @@ -96,23 +102,27 @@ class ServiceImpl GRPC_FINAL : public ::grpc::cpp::test::util::TestService::Serv } return Status::OK; } + + int bidi_stream_count() { return bidi_stream_count_; } + + int response_stream_count() { return response_stream_count_; } + + private: + int bidi_stream_count_; + int response_stream_count_; }; class CrashTest : public ::testing::Test { protected: CrashTest() {} - std::unique_ptr<Server> - CreateServerAndClient(const std::string& mode) { + std::unique_ptr<Server> CreateServerAndClient(const std::string& mode) { auto port = grpc_pick_unused_port_or_die(); std::ostringstream addr_stream; addr_stream << "localhost:" << port; auto addr = addr_stream.str(); - client_.reset(new SubProcess({ - g_root + "/server_crash_test_client", - "--address=" + addr, - "--mode=" + mode - })); + client_.reset(new SubProcess({g_root + "/server_crash_test_client", + "--address=" + addr, "--mode=" + mode})); GPR_ASSERT(client_); ServerBuilder builder; @@ -121,9 +131,11 @@ class CrashTest : public ::testing::Test { return builder.BuildAndStart(); } - void KillClient() { - client_.reset(); - } + void KillClient() { client_.reset(); } + + bool HadOneBidiStream() { return service_.bidi_stream_count() == 1; } + + bool HadOneResponseStream() { return service_.response_stream_count() == 1; } private: std::unique_ptr<SubProcess> client_; @@ -136,6 +148,7 @@ TEST_F(CrashTest, ResponseStream) { gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(5))); KillClient(); server->Shutdown(); + GPR_ASSERT(HadOneResponseStream()); } TEST_F(CrashTest, BidiStream) { @@ -144,6 +157,7 @@ TEST_F(CrashTest, BidiStream) { gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(5))); KillClient(); server->Shutdown(); + GPR_ASSERT(HadOneBidiStream()); } } // namespace diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc index 874510e54f..e351059246 100644 --- a/test/cpp/interop/interop_client.cc +++ b/test/cpp/interop/interop_client.cc @@ -57,8 +57,8 @@ const std::vector<int> response_stream_sizes = {31415, 9, 2653, 58979}; const int kNumResponseMessages = 2000; const int kResponseMessageSize = 1030; const int kReceiveDelayMilliSeconds = 20; -const int kLargeRequestSize = 314159; -const int kLargeResponseSize = 271812; +const int kLargeRequestSize = 271828; +const int kLargeResponseSize = 314159; } // namespace InteropClient::InteropClient(std::shared_ptr<ChannelInterface> channel) diff --git a/test/cpp/qps/async_streaming_ping_pong_test.cc b/test/cpp/qps/async_streaming_ping_pong_test.cc index d4871c0ba1..411df4d32a 100644 --- a/test/cpp/qps/async_streaming_ping_pong_test.cc +++ b/test/cpp/qps/async_streaming_ping_pong_test.cc @@ -31,12 +31,15 @@ * */ +#include <set> + #include <grpc/support/log.h> #include <signal.h> #include "test/cpp/qps/driver.h" #include "test/cpp/qps/report.h" +#include "test/cpp/util/benchmark_config.h" namespace grpc { namespace testing { @@ -64,16 +67,17 @@ static void RunAsyncStreamingPingPong() { const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - ReportQPS(*result); - ReportLatency(*result); + GetReporter()->ReportQPS(*result); + GetReporter()->ReportLatency(*result); } } // namespace testing } // namespace grpc int main(int argc, char** argv) { + grpc::testing::InitBenchmark(&argc, &argv, true); + signal(SIGPIPE, SIG_IGN); grpc::testing::RunAsyncStreamingPingPong(); - return 0; } diff --git a/test/cpp/qps/async_unary_ping_pong_test.cc b/test/cpp/qps/async_unary_ping_pong_test.cc index 35f188c986..eda31b5744 100644 --- a/test/cpp/qps/async_unary_ping_pong_test.cc +++ b/test/cpp/qps/async_unary_ping_pong_test.cc @@ -31,12 +31,15 @@ * */ +#include <set> + #include <grpc/support/log.h> #include <signal.h> #include "test/cpp/qps/driver.h" #include "test/cpp/qps/report.h" +#include "test/cpp/util/benchmark_config.h" namespace grpc { namespace testing { @@ -64,16 +67,16 @@ static void RunAsyncUnaryPingPong() { const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - ReportQPS(*result); - ReportLatency(*result); + GetReporter()->ReportQPS(*result); + GetReporter()->ReportLatency(*result); } - } // namespace testing } // namespace grpc int main(int argc, char** argv) { + grpc::testing::InitBenchmark(&argc, &argv, true); signal(SIGPIPE, SIG_IGN); - grpc::testing::RunAsyncUnaryPingPong(); + grpc::testing::RunAsyncUnaryPingPong(); return 0; } diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc index 008830de4e..281e2e8119 100644 --- a/test/cpp/qps/qps_driver.cc +++ b/test/cpp/qps/qps_driver.cc @@ -31,12 +31,15 @@ * */ +#include <memory> +#include <set> + #include <gflags/gflags.h> #include <grpc/support/log.h> #include "test/cpp/qps/driver.h" #include "test/cpp/qps/report.h" -#include "test/cpp/util/test_config.h" +#include "test/cpp/util/benchmark_config.h" DEFINE_int32(num_clients, 1, "Number of client binaries"); DEFINE_int32(num_servers, 1, "Number of server binaries"); @@ -68,9 +71,10 @@ using grpc::testing::ServerType; using grpc::testing::RpcType; using grpc::testing::ResourceUsage; -int main(int argc, char** argv) { - grpc::testing::InitTest(&argc, &argv, true); +namespace grpc { +namespace testing { +static void QpsDriver() { RpcType rpc_type; GPR_ASSERT(RpcType_Parse(FLAGS_rpc_type, &rpc_type)); @@ -107,9 +111,20 @@ int main(int argc, char** argv) { client_config, FLAGS_num_clients, server_config, FLAGS_num_servers, FLAGS_warmup_seconds, FLAGS_benchmark_seconds, FLAGS_local_workers); - ReportQPSPerCore(*result, server_config); - ReportLatency(*result); - ReportTimes(*result); + GetReporter()->ReportQPS(*result); + GetReporter()->ReportQPSPerCore(*result, server_config); + GetReporter()->ReportLatency(*result); + GetReporter()->ReportTimes(*result); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::InitBenchmark(&argc, &argv, true); + + signal(SIGPIPE, SIG_IGN); + grpc::testing::QpsDriver(); return 0; } diff --git a/test/cpp/qps/qps_test.cc b/test/cpp/qps/qps_test.cc index 9a81d0fc90..63a37ae07e 100644 --- a/test/cpp/qps/qps_test.cc +++ b/test/cpp/qps/qps_test.cc @@ -31,12 +31,15 @@ * */ +#include <set> + #include <grpc/support/log.h> #include <signal.h> #include "test/cpp/qps/driver.h" #include "test/cpp/qps/report.h" +#include "test/cpp/util/benchmark_config.h" namespace grpc { namespace testing { @@ -64,14 +67,16 @@ static void RunQPS() { const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - ReportQPSPerCore(*result, server_config); - ReportLatency(*result); + GetReporter()->ReportQPSPerCore(*result, server_config); + GetReporter()->ReportLatency(*result); } } // namespace testing } // namespace grpc int main(int argc, char** argv) { + grpc::testing::InitBenchmark(&argc, &argv, true); + signal(SIGPIPE, SIG_IGN); grpc::testing::RunQPS(); diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc index 3115ff3bfb..e116175e3b 100644 --- a/test/cpp/qps/report.cc +++ b/test/cpp/qps/report.cc @@ -39,27 +39,55 @@ namespace grpc { namespace testing { -// QPS: XXX -void ReportQPS(const ScenarioResult& result) { +void CompositeReporter::add(std::unique_ptr<Reporter> reporter) { + reporters_.emplace_back(std::move(reporter)); +} + +void CompositeReporter::ReportQPS(const ScenarioResult& result) const { + for (size_t i = 0; i < reporters_.size(); ++i) { + reporters_[i]->ReportQPS(result); + } +} + +void CompositeReporter::ReportQPSPerCore(const ScenarioResult& result, + const ServerConfig& config) const { + for (size_t i = 0; i < reporters_.size(); ++i) { + reporters_[i]->ReportQPSPerCore(result, config); + } +} + +void CompositeReporter::ReportLatency(const ScenarioResult& result) const { + for (size_t i = 0; i < reporters_.size(); ++i) { + reporters_[i]->ReportLatency(result); + } +} + +void CompositeReporter::ReportTimes(const ScenarioResult& result) const { + for (size_t i = 0; i < reporters_.size(); ++i) { + reporters_[i]->ReportTimes(result); + } +} + + +void GprLogReporter::ReportQPS(const ScenarioResult& result) const { gpr_log(GPR_INFO, "QPS: %.1f", result.latencies.Count() / average(result.client_resources, [](ResourceUsage u) { return u.wall_time; })); } -// QPS: XXX (YYY/server core) -void ReportQPSPerCore(const ScenarioResult& result, - const ServerConfig& server_config) { - auto qps = result.latencies.Count() / - average(result.client_resources, - [](ResourceUsage u) { return u.wall_time; }); +void GprLogReporter::ReportQPSPerCore(const ScenarioResult& result, + const ServerConfig& server_config) const { + auto qps = + result.latencies.Count() / + average(result.client_resources, + [](ResourceUsage u) { return u.wall_time; }); gpr_log(GPR_INFO, "QPS: %.1f (%.1f/server core)", qps, qps / server_config.threads()); } -// Latency (50/90/95/99/99.9%-ile): AA/BB/CC/DD/EE us -void ReportLatency(const ScenarioResult& result) { +void GprLogReporter::ReportLatency(const ScenarioResult& result) const { gpr_log(GPR_INFO, "Latencies (50/90/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f/%.1f us", result.latencies.Percentile(50) / 1000, @@ -69,7 +97,7 @@ void ReportLatency(const ScenarioResult& result) { result.latencies.Percentile(99.9) / 1000); } -void ReportTimes(const ScenarioResult& result) { +void GprLogReporter::ReportTimes(const ScenarioResult& result) const { gpr_log(GPR_INFO, "Server system time: %.2f%%", 100.0 * sum(result.server_resources, [](ResourceUsage u) { return u.system_time; }) / diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h index 343e426ca4..630275ecda 100644 --- a/test/cpp/qps/report.h +++ b/test/cpp/qps/report.h @@ -34,22 +34,77 @@ #ifndef TEST_QPS_REPORT_H #define TEST_QPS_REPORT_H +#include <memory> +#include <set> +#include <vector> +#include <grpc++/config.h> + #include "test/cpp/qps/driver.h" +#include "test/cpp/qps/qpstest.grpc.pb.h" namespace grpc { namespace testing { -// QPS: XXX -void ReportQPS(const ScenarioResult& result); -// QPS: XXX (YYY/server core) -void ReportQPSPerCore(const ScenarioResult& result, const ServerConfig& config); -// Latency (50/90/95/99/99.9%-ile): AA/BB/CC/DD/EE us -void ReportLatency(const ScenarioResult& result); -// Server system time: XX% -// Server user time: XX% -// Client system time: XX% -// Client user time: XX% -void ReportTimes(const ScenarioResult& result); +/** Interface for all reporters. */ +class Reporter { + public: + /** Construct a reporter with the given \a name. */ + Reporter(const string& name) : name_(name) {} + + virtual ~Reporter() {} + + /** Returns this reporter's name. + * + * Names are constants, set at construction time. */ + string name() const { return name_; } + + /** Reports QPS for the given \a result. */ + virtual void ReportQPS(const ScenarioResult& result) const = 0; + + /** Reports QPS per core as (YYY/server core). */ + virtual void ReportQPSPerCore(const ScenarioResult& result, + const ServerConfig& config) const = 0; + + /** Reports latencies for the 50, 90, 95, 99 and 99.9 percentiles, in ms. */ + virtual void ReportLatency(const ScenarioResult& result) const = 0; + + /** Reports system and user time for client and server systems. */ + virtual void ReportTimes(const ScenarioResult& result) const = 0; + + private: + const string name_; +}; + +/** A composite for all reporters to be considered. */ +class CompositeReporter : public Reporter { + public: + CompositeReporter() : Reporter("CompositeReporter") {} + + /** Adds a \a reporter to the composite. */ + void add(std::unique_ptr<Reporter> reporter); + + void ReportQPS(const ScenarioResult& result) const GRPC_OVERRIDE; + void ReportQPSPerCore(const ScenarioResult& result, + const ServerConfig& config) const GRPC_OVERRIDE; + void ReportLatency(const ScenarioResult& result) const GRPC_OVERRIDE; + void ReportTimes(const ScenarioResult& result) const GRPC_OVERRIDE; + + private: + std::vector<std::unique_ptr<Reporter> > reporters_; +}; + +/** Reporter to gpr_log(GPR_INFO). */ +class GprLogReporter : public Reporter { + public: + GprLogReporter(const string& name) : Reporter(name) {} + + private: + void ReportQPS(const ScenarioResult& result) const GRPC_OVERRIDE; + void ReportQPSPerCore(const ScenarioResult& result, + const ServerConfig& config) const GRPC_OVERRIDE; + void ReportLatency(const ScenarioResult& result) const GRPC_OVERRIDE; + void ReportTimes(const ScenarioResult& result) const GRPC_OVERRIDE; +}; } // namespace testing } // namespace grpc diff --git a/test/cpp/qps/sync_streaming_ping_pong_test.cc b/test/cpp/qps/sync_streaming_ping_pong_test.cc index 218306846b..d53905a779 100644 --- a/test/cpp/qps/sync_streaming_ping_pong_test.cc +++ b/test/cpp/qps/sync_streaming_ping_pong_test.cc @@ -31,12 +31,15 @@ * */ +#include <set> + #include <grpc/support/log.h> #include <signal.h> #include "test/cpp/qps/driver.h" #include "test/cpp/qps/report.h" +#include "test/cpp/util/benchmark_config.h" namespace grpc { namespace testing { @@ -63,14 +66,15 @@ static void RunSynchronousStreamingPingPong() { const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - ReportQPS(*result); - ReportLatency(*result); + GetReporter()->ReportQPS(*result); + GetReporter()->ReportLatency(*result); } - } // namespace testing } // namespace grpc int main(int argc, char** argv) { + grpc::testing::InitBenchmark(&argc, &argv, true); + signal(SIGPIPE, SIG_IGN); grpc::testing::RunSynchronousStreamingPingPong(); diff --git a/test/cpp/qps/sync_unary_ping_pong_test.cc b/test/cpp/qps/sync_unary_ping_pong_test.cc index 137ef79f2f..d276d13a43 100644 --- a/test/cpp/qps/sync_unary_ping_pong_test.cc +++ b/test/cpp/qps/sync_unary_ping_pong_test.cc @@ -31,12 +31,15 @@ * */ +#include <set> + #include <grpc/support/log.h> #include <signal.h> #include "test/cpp/qps/driver.h" #include "test/cpp/qps/report.h" +#include "test/cpp/util/benchmark_config.h" namespace grpc { namespace testing { @@ -63,14 +66,16 @@ static void RunSynchronousUnaryPingPong() { const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2); - ReportQPS(*result); - ReportLatency(*result); + GetReporter()->ReportQPS(*result); + GetReporter()->ReportLatency(*result); } } // namespace testing } // namespace grpc int main(int argc, char** argv) { + grpc::testing::InitBenchmark(&argc, &argv, true); + signal(SIGPIPE, SIG_IGN); grpc::testing::RunSynchronousUnaryPingPong(); diff --git a/test/cpp/util/benchmark_config.cc b/test/cpp/util/benchmark_config.cc new file mode 100644 index 0000000000..5b3c1daf5d --- /dev/null +++ b/test/cpp/util/benchmark_config.cc @@ -0,0 +1,69 @@ +/* + * + * 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 "test/cpp/util/benchmark_config.h" + +DEFINE_bool(enable_log_reporter, true, + "Enable reporting of benchmark results through GprLog"); + +// 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; + +namespace grpc { +namespace testing { + +void InitBenchmark(int* argc, char*** argv, bool remove_flags) { + ParseCommandLineFlags(argc, argv, remove_flags); +} + +static std::shared_ptr<Reporter> InitBenchmarkReporters() { + auto* composite_reporter = new CompositeReporter; + if (FLAGS_enable_log_reporter) { + composite_reporter->add( + std::unique_ptr<Reporter>(new GprLogReporter("LogReporter"))); + } + return std::shared_ptr<Reporter>(composite_reporter); +} + +std::shared_ptr<Reporter> GetReporter() { + static std::shared_ptr<Reporter> reporter(InitBenchmarkReporters()); + return reporter; +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/util/benchmark_config.h b/test/cpp/util/benchmark_config.h new file mode 100644 index 0000000000..6b308a15ff --- /dev/null +++ b/test/cpp/util/benchmark_config.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 GRPC_TEST_CPP_UTIL_BENCHMARK_CONFIG_H +#define GRPC_TEST_CPP_UTIL_BENCHMARK_CONFIG_H + +#include <memory> +#include <vector> + +#include "test/cpp/qps/report.h" + +namespace grpc { +namespace testing { + +void InitBenchmark(int* argc, char*** argv, bool remove_flags); + +/** Returns the benchmark Reporter instance. + * + * The returned instance will take care of generating reports for all the actual + * reporters configured via the "enable_*_reporter" command line flags (see + * benchmark_config.cc). */ +std::shared_ptr<Reporter> GetReporter(); + +} // namespace testing +} // namespace grpc + +#endif // GRPC_TEST_CPP_UTIL_BENCHMARK_CONFIG_H |