diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e8582d9af5e..1d14d5e0e3a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,7 +81,7 @@ How to get your contributions merged smoothly and quickly. copyright holder for the contribution (yourself, if you are signing the individual CLA, or your company, for corporate CLAs) in the same PR as your contribution. This needs to be done only once, for each company, or - individual. + individual. Please keep this file in alphabetical order. - Maintain **clean commit history** and use **meaningful commit messages**. PRs with messy commit history are difficult to review and won't be merged. diff --git a/WORKSPACE b/WORKSPACE index a547c24cbe2..cd2718204d1 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,45 +1,59 @@ -workspace(name="com_github_grpc_grpc") +workspace(name = "com_github_grpc_grpc") load("//bazel:grpc_deps.bzl", "grpc_deps", "grpc_test_only_deps") + grpc_deps() + grpc_test_only_deps() +register_execution_platforms( + "//third_party/toolchains:all", +) + +register_toolchains( + "//third_party/toolchains:all", +) + new_http_archive( - name="cython", - sha256="d68138a2381afbdd0876c3cb2a22389043fa01c4badede1228ee073032b07a27", - urls=[ + name = "cython", + build_file = "//third_party:cython.BUILD", + sha256 = "d68138a2381afbdd0876c3cb2a22389043fa01c4badede1228ee073032b07a27", + strip_prefix = "cython-c2b80d87658a8525ce091cbe146cb7eaa29fed5c", + urls = [ "https://github.com/cython/cython/archive/c2b80d87658a8525ce091cbe146cb7eaa29fed5c.tar.gz", ], - strip_prefix="cython-c2b80d87658a8525ce091cbe146cb7eaa29fed5c", - build_file="//third_party:cython.BUILD", ) load("//third_party/py:python_configure.bzl", "python_configure") -python_configure(name="local_config_python") + +python_configure(name = "local_config_python") git_repository( - name="io_bazel_rules_python", - remote="https://github.com/bazelbuild/rules_python.git", - commit="8b5d0683a7d878b28fffe464779c8a53659fc645", + name = "io_bazel_rules_python", + commit = "8b5d0683a7d878b28fffe464779c8a53659fc645", + remote = "https://github.com/bazelbuild/rules_python.git", ) load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories", "pip_import") pip_repositories() + pip_import( - name="grpc_python_dependencies", - requirements="//:requirements.bazel.txt", + name = "grpc_python_dependencies", + requirements = "//:requirements.bazel.txt", ) load("@grpc_python_dependencies//:requirements.bzl", "pip_install") + pip_install() # NOTE(https://github.com/pubref/rules_protobuf/pull/196): Switch to upstream repo after this gets merged. git_repository( - name="org_pubref_rules_protobuf", - remote="https://github.com/ghostwriternr/rules_protobuf", - tag="v0.8.2.1-alpha", + name = "org_pubref_rules_protobuf", + remote = "https://github.com/ghostwriternr/rules_protobuf", + tag = "v0.8.2.1-alpha", ) load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_repositories") + py_proto_repositories() diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index 159ebd5d1fe..65fe5a10aa2 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -131,7 +131,7 @@ def grpc_proto_library( generate_mocks = generate_mocks, ) -def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++", size = "medium", timeout = "moderate", tags = []): +def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++", size = "medium", timeout = "moderate", tags = [], exec_compatible_with = []): copts = [] if language.upper() == "C": copts = if_not_windows(["-std=c99"]) @@ -145,6 +145,7 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data "linkopts": if_not_windows(["-pthread"]), "size": size, "timeout": timeout, + "exec_compatible_with": exec_compatible_with, } if uses_polling: native.cc_test(testonly = True, tags = ["manual"], **args) @@ -162,6 +163,7 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data "$(location %s)" % name, ] + args["args"], tags = tags, + exec_compatible_with = exec_compatible_with, ) else: native.cc_test(**args) diff --git a/doc/grpc_release_schedule.md b/doc/grpc_release_schedule.md new file mode 100644 index 00000000000..bacd3758593 --- /dev/null +++ b/doc/grpc_release_schedule.md @@ -0,0 +1,22 @@ +# gRPC Release Schedule + +Below is the release schedule for gRPC [Java](https://github.com/grpc/grpc-java/releases), [Go](https://github.com/grpc/grpc-go/releases) and [Core](https://github.com/grpc/grpc/releases) and its dependent languages C++, C#, Objective-C, PHP, Python and Ruby. + +Releases are scheduled every six weeks on Tuesdays on a best effort basis. In some unavoidable situations a release may be delayed or a language may skip a release altogether and do the next release to catch up with other languages. See the past releases in the links above. A six-week cycle gives us a good balance between delivering new features/fixes quickly and keeping the release overhead low. + +Releases are cut from release branches. For Core and Java repos, the release branch is cut two weeks before the scheduled release date. For Go, the branch is cut just before the release. An RC (release candidate) is published for Core and its dependent languages just after the branch cut. This RC is later promoted to release version if no further changes are made to the release branch. We do our best to keep head of master branch stable at all times regardless of release schedule. Daily build packages from master branch for C#, PHP, Python, Ruby and Protoc plugins are published on [packages.grpc.io](https://packages.grpc.io/). If you depend on gRPC in production we recommend to set up your CI system to test the RCs and, if possible, the daily builds. + +Names of gRPC releases are [here](https://github.com/grpc/grpc/blob/master/doc/g_stands_for.md). + +Release |Scheduled Branch Cut|Scheduled Release Date +--------|--------------------|------------- +v1.17.0 |Nov 19, 2018 |Dec 4, 2018 +v1.18.0 |Jan 2, 2019 |Jan 15, 2019 +v1.19.0 |Feb 12, 2019 |Feb 26, 2019 +v1.20.0 |Mar 26, 2019 |Apr 9, 2019 +v1.21.0 |May 7, 2019 |May 21, 2019 +v1.22.0 |Jun 18, 2019 |Jul 2, 2019 +v1.23.0 |Jul 30, 2019 |Aug 13, 2019 +v1.24.0 |Sept 10, 2019 |Sept 24, 2019 +v1.25.0 |Oct 22, 2019 |Nov 5, 2019 +v1.26.0 |Dec 3, 2019 |Dec 17, 2019 diff --git a/doc/naming.md b/doc/naming.md index 581c550567f..5e54ca67b31 100644 --- a/doc/naming.md +++ b/doc/naming.md @@ -51,7 +51,9 @@ but may not be supported in other languages: - `ipv6:address[:port][,address[:port],...]` -- IPv6 addresses - Can specify multiple comma-delimited addresses of the form `address[:port]`: - - `address` is the IPv6 address to use. + - `address` is the IPv6 address to use. To use with a `port` the `address` + must enclosed in literal square brakets (`[` and `]`). Example: + `ipv6:[2607:f8b0:400e:c00::ef]:443` or `ipv6:[::]:1234` - `port` is the port to use. If not specified, 443 is used. In the future, additional schemes such as `etcd` could be added. diff --git a/doc/python/sphinx/conf.py b/doc/python/sphinx/conf.py index 1eb3a5de7fd..307c3bdaf60 100644 --- a/doc/python/sphinx/conf.py +++ b/doc/python/sphinx/conf.py @@ -19,6 +19,7 @@ import sys PYTHON_FOLDER = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..', 'src', 'python') sys.path.insert(0, os.path.join(PYTHON_FOLDER, 'grpcio')) +sys.path.insert(0, os.path.join(PYTHON_FOLDER, 'grpcio_channelz')) sys.path.insert(0, os.path.join(PYTHON_FOLDER, 'grpcio_health_checking')) sys.path.insert(0, os.path.join(PYTHON_FOLDER, 'grpcio_reflection')) sys.path.insert(0, os.path.join(PYTHON_FOLDER, 'grpcio_testing')) @@ -63,6 +64,8 @@ autodoc_default_options = { autodoc_mock_imports = [ 'grpc._cython', + 'grpc_channelz.v1.channelz_pb2', + 'grpc_channelz.v1.channelz_pb2_grpc', 'grpc_health.v1.health_pb2', 'grpc_health.v1.health_pb2_grpc', 'grpc_reflection.v1alpha.reflection_pb2', diff --git a/doc/python/sphinx/grpc_channelz.rst b/doc/python/sphinx/grpc_channelz.rst new file mode 100644 index 00000000000..f65793a071a --- /dev/null +++ b/doc/python/sphinx/grpc_channelz.rst @@ -0,0 +1,12 @@ +gRPC Channelz +==================== + +What is gRPC Channelz? +--------------------------------------------- + +Design Document `gRPC Channelz `_ + +Module Contents +--------------- + +.. automodule:: grpc_channelz.v1.channelz diff --git a/doc/python/sphinx/index.rst b/doc/python/sphinx/index.rst index 322ca33e157..2f8a47a0747 100644 --- a/doc/python/sphinx/index.rst +++ b/doc/python/sphinx/index.rst @@ -10,6 +10,7 @@ API Reference :caption: Contents: grpc + grpc_channelz grpc_health_checking grpc_reflection grpc_testing diff --git a/examples/python/helloworld/greeter_client.py b/examples/python/helloworld/greeter_client.py index 24b49ac2336..ee2032a9e6e 100644 --- a/examples/python/helloworld/greeter_client.py +++ b/examples/python/helloworld/greeter_client.py @@ -14,6 +14,7 @@ """The Python implementation of the GRPC helloworld.Greeter client.""" from __future__ import print_function +import logging import grpc @@ -32,4 +33,5 @@ def run(): if __name__ == '__main__': + logging.basicConfig() run() diff --git a/examples/python/helloworld/greeter_client_with_options.py b/examples/python/helloworld/greeter_client_with_options.py index 7eda8c9066f..d15871b5195 100644 --- a/examples/python/helloworld/greeter_client_with_options.py +++ b/examples/python/helloworld/greeter_client_with_options.py @@ -14,6 +14,7 @@ """The Python implementation of the GRPC helloworld.Greeter client with channel options and call timeout parameters.""" from __future__ import print_function +import logging import grpc @@ -41,4 +42,5 @@ def run(): if __name__ == '__main__': + logging.basicConfig() run() diff --git a/examples/python/helloworld/greeter_server.py b/examples/python/helloworld/greeter_server.py index c355662ef86..e3b4f2c1ff9 100644 --- a/examples/python/helloworld/greeter_server.py +++ b/examples/python/helloworld/greeter_server.py @@ -15,6 +15,7 @@ from concurrent import futures import time +import logging import grpc @@ -43,4 +44,5 @@ def serve(): if __name__ == '__main__': + logging.basicConfig() serve() diff --git a/examples/python/helloworld/greeter_server_with_reflection.py b/examples/python/helloworld/greeter_server_with_reflection.py index 5ba8782dfca..5acedbcb71f 100644 --- a/examples/python/helloworld/greeter_server_with_reflection.py +++ b/examples/python/helloworld/greeter_server_with_reflection.py @@ -15,6 +15,7 @@ from concurrent import futures import time +import logging import grpc from grpc_reflection.v1alpha import reflection @@ -49,4 +50,5 @@ def serve(): if __name__ == '__main__': + logging.basicConfig() serve() diff --git a/examples/python/interceptors/default_value/greeter_client.py b/examples/python/interceptors/default_value/greeter_client.py index da21ac68ec5..25834c2bbdd 100644 --- a/examples/python/interceptors/default_value/greeter_client.py +++ b/examples/python/interceptors/default_value/greeter_client.py @@ -14,6 +14,7 @@ """The Python implementation of the gRPC helloworld.Greeter client.""" from __future__ import print_function +import logging import grpc @@ -39,4 +40,5 @@ def run(): if __name__ == '__main__': + logging.basicConfig() run() diff --git a/examples/python/interceptors/headers/greeter_client.py b/examples/python/interceptors/headers/greeter_client.py index 6a09a3b9c50..712539850d3 100644 --- a/examples/python/interceptors/headers/greeter_client.py +++ b/examples/python/interceptors/headers/greeter_client.py @@ -14,6 +14,7 @@ """The Python implementation of the GRPC helloworld.Greeter client.""" from __future__ import print_function +import logging import grpc @@ -37,4 +38,5 @@ def run(): if __name__ == '__main__': + logging.basicConfig() run() diff --git a/examples/python/interceptors/headers/greeter_server.py b/examples/python/interceptors/headers/greeter_server.py index 01968609b53..6b0f4058bcd 100644 --- a/examples/python/interceptors/headers/greeter_server.py +++ b/examples/python/interceptors/headers/greeter_server.py @@ -15,6 +15,7 @@ from concurrent import futures import time +import logging import grpc @@ -49,4 +50,5 @@ def serve(): if __name__ == '__main__': + logging.basicConfig() serve() diff --git a/examples/python/multiplex/multiplex_client.py b/examples/python/multiplex/multiplex_client.py index 19d39ce66eb..155f85c4b0c 100644 --- a/examples/python/multiplex/multiplex_client.py +++ b/examples/python/multiplex/multiplex_client.py @@ -17,6 +17,7 @@ from __future__ import print_function import random import time +import logging import grpc @@ -126,4 +127,5 @@ def run(): if __name__ == '__main__': + logging.basicConfig() run() diff --git a/examples/python/multiplex/multiplex_server.py b/examples/python/multiplex/multiplex_server.py index 70dec3c9390..c01824b3a97 100644 --- a/examples/python/multiplex/multiplex_server.py +++ b/examples/python/multiplex/multiplex_server.py @@ -16,6 +16,7 @@ from concurrent import futures import time import math +import logging import grpc @@ -136,4 +137,5 @@ def serve(): if __name__ == '__main__': + logging.basicConfig() serve() diff --git a/examples/python/route_guide/route_guide_client.py b/examples/python/route_guide/route_guide_client.py index b4ff3239ba8..dc93fb44379 100644 --- a/examples/python/route_guide/route_guide_client.py +++ b/examples/python/route_guide/route_guide_client.py @@ -16,6 +16,7 @@ from __future__ import print_function import random +import logging import grpc @@ -116,4 +117,5 @@ def run(): if __name__ == '__main__': + logging.basicConfig() run() diff --git a/examples/python/route_guide/route_guide_server.py b/examples/python/route_guide/route_guide_server.py index 1969fdd378d..e00cb699084 100644 --- a/examples/python/route_guide/route_guide_server.py +++ b/examples/python/route_guide/route_guide_server.py @@ -16,6 +16,7 @@ from concurrent import futures import time import math +import logging import grpc @@ -126,4 +127,5 @@ def serve(): if __name__ == '__main__': + logging.basicConfig() serve() diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 17a43fab0f1..a9fb27946e0 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -293,7 +293,7 @@ typedef struct { "grpc.max_channel_trace_event_memory_per_node" /** If non-zero, gRPC library will track stats and information at at per channel * level. Disabling channelz naturally disables channel tracing. The default - * is for channelz to be disabled. */ + * is for channelz to be enabled. */ #define GRPC_ARG_ENABLE_CHANNELZ "grpc.enable_channelz" /** If non-zero, Cronet transport will coalesce packets to fewer frames * when possible. */ @@ -350,6 +350,11 @@ typedef struct { /** If set, inhibits health checking (which may be enabled via the * service config.) */ #define GRPC_ARG_INHIBIT_HEALTH_CHECKING "grpc.inhibit_health_checking" +/** If set, determines the number of milliseconds that the c-ares based + * DNS resolver will wait on queries before cancelling them. The default value + * is 10000. Setting this to "0" will disable c-ares query timeouts + * entirely. */ +#define GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS "grpc.dns_ares_query_timeout" /** \} */ /** Result of a grpc call. If the caller satisfies the prerequisites of a diff --git a/include/grpcpp/generic/generic_stub.h b/include/grpcpp/generic/generic_stub.h index d509d9a5206..eb014184e4a 100644 --- a/include/grpcpp/generic/generic_stub.h +++ b/include/grpcpp/generic/generic_stub.h @@ -24,6 +24,7 @@ #include #include #include +#include #include namespace grpc { @@ -76,6 +77,10 @@ class GenericStub final { const ByteBuffer* request, ByteBuffer* response, std::function on_completion); + void PrepareBidiStreamingCall( + ClientContext* context, const grpc::string& method, + experimental::ClientBidiReactor* reactor); + private: GenericStub* stub_; }; diff --git a/include/grpcpp/impl/codegen/byte_buffer.h b/include/grpcpp/impl/codegen/byte_buffer.h index abba5549b86..53ecb53371b 100644 --- a/include/grpcpp/impl/codegen/byte_buffer.h +++ b/include/grpcpp/impl/codegen/byte_buffer.h @@ -45,8 +45,10 @@ template class RpcMethodHandler; template class ServerStreamingHandler; -template +template class CallbackUnaryHandler; +template +class CallbackServerStreamingHandler; template class ErrorMethodHandler; template @@ -156,8 +158,10 @@ class ByteBuffer final { friend class internal::RpcMethodHandler; template friend class internal::ServerStreamingHandler; - template + template friend class internal::CallbackUnaryHandler; + template + friend class ::grpc::internal::CallbackServerStreamingHandler; template friend class internal::ErrorMethodHandler; template diff --git a/include/grpcpp/impl/codegen/callback_common.h b/include/grpcpp/impl/codegen/callback_common.h index 51367cf550c..a3c8c41246c 100644 --- a/include/grpcpp/impl/codegen/callback_common.h +++ b/include/grpcpp/impl/codegen/callback_common.h @@ -32,6 +32,8 @@ namespace grpc { namespace internal { /// An exception-safe way of invoking a user-specified callback function +// TODO(vjpai): decide whether it is better for this to take a const lvalue +// parameter or an rvalue parameter, or if it even matters template void CatchingCallback(Func&& func, Args&&... args) { #if GRPC_ALLOW_EXCEPTIONS @@ -45,6 +47,20 @@ void CatchingCallback(Func&& func, Args&&... args) { #endif // GRPC_ALLOW_EXCEPTIONS } +template +ReturnType* CatchingReactorCreator(Func&& func, Args&&... args) { +#if GRPC_ALLOW_EXCEPTIONS + try { + return func(std::forward(args)...); + } catch (...) { + // fail the RPC, don't crash the library + return nullptr; + } +#else // GRPC_ALLOW_EXCEPTIONS + return func(std::forward(args)...); +#endif // GRPC_ALLOW_EXCEPTIONS +} + // The contract on these tags is that they are single-shot. They must be // constructed and then fired at exactly one point. There is no expectation // that they can be reused without reconstruction. @@ -145,18 +161,19 @@ class CallbackWithSuccessTag // or on a tag that has been Set before unless the tag has been cleared. void Set(grpc_call* call, std::function f, CompletionQueueTag* ops) { + GPR_CODEGEN_ASSERT(call_ == nullptr); + g_core_codegen_interface->grpc_call_ref(call); call_ = call; func_ = std::move(f); ops_ = ops; - g_core_codegen_interface->grpc_call_ref(call); functor_run = &CallbackWithSuccessTag::StaticRun; } void Clear() { if (call_ != nullptr) { - func_ = nullptr; grpc_call* call = call_; call_ = nullptr; + func_ = nullptr; g_core_codegen_interface->grpc_call_unref(call); } } @@ -182,11 +199,11 @@ class CallbackWithSuccessTag } void Run(bool ok) { void* ignored = ops_; - bool new_ok = ok; // Allow a "false" return value from FinalizeResult to silence the // callback, just as it silences a CQ tag in the async cases - bool do_callback = ops_->FinalizeResult(&ignored, &new_ok); - GPR_CODEGEN_ASSERT(ignored == ops_); + auto* ops = ops_; + bool do_callback = ops_->FinalizeResult(&ignored, &ok); + GPR_CODEGEN_ASSERT(ignored == ops); if (do_callback) { CatchingCallback(func_, ok); diff --git a/include/grpcpp/impl/codegen/channel_interface.h b/include/grpcpp/impl/codegen/channel_interface.h index 6ec1ffb8c7d..728a7b90496 100644 --- a/include/grpcpp/impl/codegen/channel_interface.h +++ b/include/grpcpp/impl/codegen/channel_interface.h @@ -53,6 +53,12 @@ template class ClientAsyncReaderWriterFactory; template class ClientAsyncResponseReaderFactory; +template +class ClientCallbackReaderWriterFactory; +template +class ClientCallbackReaderFactory; +template +class ClientCallbackWriterFactory; class InterceptedChannel; } // namespace internal @@ -106,6 +112,12 @@ class ChannelInterface { friend class ::grpc::internal::ClientAsyncReaderWriterFactory; template friend class ::grpc::internal::ClientAsyncResponseReaderFactory; + template + friend class ::grpc::internal::ClientCallbackReaderWriterFactory; + template + friend class ::grpc::internal::ClientCallbackReaderFactory; + template + friend class ::grpc::internal::ClientCallbackWriterFactory; template friend class ::grpc::internal::BlockingUnaryCallImpl; template diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h index 4baa819091c..4d9579fd6ab 100644 --- a/include/grpcpp/impl/codegen/client_callback.h +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -88,6 +89,646 @@ class CallbackUnaryCallImpl { call.PerformOps(ops); } }; +} // namespace internal + +namespace experimental { + +// Forward declarations +template +class ClientBidiReactor; +template +class ClientReadReactor; +template +class ClientWriteReactor; + +// NOTE: The streaming objects are not actually implemented in the public API. +// These interfaces are provided for mocking only. Typical applications +// will interact exclusively with the reactors that they define. +template +class ClientCallbackReaderWriter { + public: + virtual ~ClientCallbackReaderWriter() {} + virtual void StartCall() = 0; + virtual void Write(const Request* req, WriteOptions options) = 0; + virtual void WritesDone() = 0; + virtual void Read(Response* resp) = 0; + + protected: + void BindReactor(ClientBidiReactor* reactor) { + reactor->BindStream(this); + } +}; + +template +class ClientCallbackReader { + public: + virtual ~ClientCallbackReader() {} + virtual void StartCall() = 0; + virtual void Read(Response* resp) = 0; + + protected: + void BindReactor(ClientReadReactor* reactor) { + reactor->BindReader(this); + } +}; + +template +class ClientCallbackWriter { + public: + virtual ~ClientCallbackWriter() {} + virtual void StartCall() = 0; + void Write(const Request* req) { Write(req, WriteOptions()); } + virtual void Write(const Request* req, WriteOptions options) = 0; + void WriteLast(const Request* req, WriteOptions options) { + Write(req, options.set_last_message()); + } + virtual void WritesDone() = 0; + + protected: + void BindReactor(ClientWriteReactor* reactor) { + reactor->BindWriter(this); + } +}; + +// The user must implement this reactor interface with reactions to each event +// type that gets called by the library. An empty reaction is provided by +// default +template +class ClientBidiReactor { + public: + virtual ~ClientBidiReactor() {} + virtual void OnDone(const Status& s) {} + virtual void OnReadInitialMetadataDone(bool ok) {} + virtual void OnReadDone(bool ok) {} + virtual void OnWriteDone(bool ok) {} + virtual void OnWritesDoneDone(bool ok) {} + + void StartCall() { stream_->StartCall(); } + void StartRead(Response* resp) { stream_->Read(resp); } + void StartWrite(const Request* req) { StartWrite(req, WriteOptions()); } + void StartWrite(const Request* req, WriteOptions options) { + stream_->Write(req, std::move(options)); + } + void StartWriteLast(const Request* req, WriteOptions options) { + StartWrite(req, std::move(options.set_last_message())); + } + void StartWritesDone() { stream_->WritesDone(); } + + private: + friend class ClientCallbackReaderWriter; + void BindStream(ClientCallbackReaderWriter* stream) { + stream_ = stream; + } + ClientCallbackReaderWriter* stream_; +}; + +template +class ClientReadReactor { + public: + virtual ~ClientReadReactor() {} + virtual void OnDone(const Status& s) {} + virtual void OnReadInitialMetadataDone(bool ok) {} + virtual void OnReadDone(bool ok) {} + + void StartCall() { reader_->StartCall(); } + void StartRead(Response* resp) { reader_->Read(resp); } + + private: + friend class ClientCallbackReader; + void BindReader(ClientCallbackReader* reader) { reader_ = reader; } + ClientCallbackReader* reader_; +}; + +template +class ClientWriteReactor { + public: + virtual ~ClientWriteReactor() {} + virtual void OnDone(const Status& s) {} + virtual void OnReadInitialMetadataDone(bool ok) {} + virtual void OnWriteDone(bool ok) {} + virtual void OnWritesDoneDone(bool ok) {} + + void StartCall() { writer_->StartCall(); } + void StartWrite(const Request* req) { StartWrite(req, WriteOptions()); } + void StartWrite(const Request* req, WriteOptions options) { + writer_->Write(req, std::move(options)); + } + void StartWriteLast(const Request* req, WriteOptions options) { + StartWrite(req, std::move(options.set_last_message())); + } + void StartWritesDone() { writer_->WritesDone(); } + + private: + friend class ClientCallbackWriter; + void BindWriter(ClientCallbackWriter* writer) { writer_ = writer; } + ClientCallbackWriter* writer_; +}; + +} // namespace experimental + +namespace internal { + +// Forward declare factory classes for friendship +template +class ClientCallbackReaderWriterFactory; +template +class ClientCallbackReaderFactory; +template +class ClientCallbackWriterFactory; + +template +class ClientCallbackReaderWriterImpl + : public ::grpc::experimental::ClientCallbackReaderWriter { + public: + // always allocated against a call arena, no memory free required + static void operator delete(void* ptr, std::size_t size) { + assert(size == sizeof(ClientCallbackReaderWriterImpl)); + } + + // This operator should never be called as the memory should be freed as part + // of the arena destruction. It only exists to provide a matching operator + // delete to the operator new so that some compilers will not complain (see + // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this + // there are no tests catching the compiler warning. + static void operator delete(void*, void*) { assert(0); } + + void MaybeFinish() { + if (--callbacks_outstanding_ == 0) { + reactor_->OnDone(finish_status_); + auto* call = call_.call(); + this->~ClientCallbackReaderWriterImpl(); + g_core_codegen_interface->grpc_call_unref(call); + } + } + + void StartCall() override { + // This call initiates two batches, plus any backlog, each with a callback + // 1. Send initial metadata (unless corked) + recv initial metadata + // 2. Any read backlog + // 3. Recv trailing metadata, on_completion callback + // 4. Any write backlog + started_ = true; + + start_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnReadInitialMetadataDone(ok); + MaybeFinish(); + }, + &start_ops_); + if (!start_corked_) { + start_ops_.SendInitialMetadata(&context_->send_initial_metadata_, + context_->initial_metadata_flags()); + } + start_ops_.RecvInitialMetadata(context_); + start_ops_.set_core_cq_tag(&start_tag_); + call_.PerformOps(&start_ops_); + + // Also set up the read and write tags so that they don't have to be set up + // each time + write_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnWriteDone(ok); + MaybeFinish(); + }, + &write_ops_); + write_ops_.set_core_cq_tag(&write_tag_); + + read_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnReadDone(ok); + MaybeFinish(); + }, + &read_ops_); + read_ops_.set_core_cq_tag(&read_tag_); + if (read_ops_at_start_) { + call_.PerformOps(&read_ops_); + } + + finish_tag_.Set(call_.call(), [this](bool ok) { MaybeFinish(); }, + &finish_ops_); + finish_ops_.ClientRecvStatus(context_, &finish_status_); + finish_ops_.set_core_cq_tag(&finish_tag_); + call_.PerformOps(&finish_ops_); + + if (write_ops_at_start_) { + call_.PerformOps(&write_ops_); + } + + if (writes_done_ops_at_start_) { + call_.PerformOps(&writes_done_ops_); + } + } + + void Read(Response* msg) override { + read_ops_.RecvMessage(msg); + callbacks_outstanding_++; + if (started_) { + call_.PerformOps(&read_ops_); + } else { + read_ops_at_start_ = true; + } + } + + void Write(const Request* msg, WriteOptions options) override { + if (start_corked_) { + write_ops_.SendInitialMetadata(&context_->send_initial_metadata_, + context_->initial_metadata_flags()); + start_corked_ = false; + } + // TODO(vjpai): don't assert + GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok()); + + if (options.is_last_message()) { + options.set_buffer_hint(); + write_ops_.ClientSendClose(); + } + callbacks_outstanding_++; + if (started_) { + call_.PerformOps(&write_ops_); + } else { + write_ops_at_start_ = true; + } + } + void WritesDone() override { + if (start_corked_) { + writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_, + context_->initial_metadata_flags()); + start_corked_ = false; + } + writes_done_ops_.ClientSendClose(); + writes_done_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnWritesDoneDone(ok); + MaybeFinish(); + }, + &writes_done_ops_); + writes_done_ops_.set_core_cq_tag(&writes_done_tag_); + callbacks_outstanding_++; + if (started_) { + call_.PerformOps(&writes_done_ops_); + } else { + writes_done_ops_at_start_ = true; + } + } + + private: + friend class ClientCallbackReaderWriterFactory; + + ClientCallbackReaderWriterImpl( + Call call, ClientContext* context, + ::grpc::experimental::ClientBidiReactor* reactor) + : context_(context), + call_(call), + reactor_(reactor), + start_corked_(context_->initial_metadata_corked_) { + this->BindReactor(reactor); + } + + ClientContext* context_; + Call call_; + ::grpc::experimental::ClientBidiReactor* reactor_; + + CallOpSet start_ops_; + CallbackWithSuccessTag start_tag_; + bool start_corked_; + + CallOpSet finish_ops_; + CallbackWithSuccessTag finish_tag_; + Status finish_status_; + + CallOpSet + write_ops_; + CallbackWithSuccessTag write_tag_; + bool write_ops_at_start_{false}; + + CallOpSet writes_done_ops_; + CallbackWithSuccessTag writes_done_tag_; + bool writes_done_ops_at_start_{false}; + + CallOpSet> read_ops_; + CallbackWithSuccessTag read_tag_; + bool read_ops_at_start_{false}; + + // Minimum of 2 outstanding callbacks to pre-register for start and finish + std::atomic_int callbacks_outstanding_{2}; + bool started_{false}; +}; + +template +class ClientCallbackReaderWriterFactory { + public: + static void Create( + ChannelInterface* channel, const ::grpc::internal::RpcMethod& method, + ClientContext* context, + ::grpc::experimental::ClientBidiReactor* reactor) { + Call call = channel->CreateCall(method, context, channel->CallbackCQ()); + + g_core_codegen_interface->grpc_call_ref(call.call()); + new (g_core_codegen_interface->grpc_call_arena_alloc( + call.call(), sizeof(ClientCallbackReaderWriterImpl))) + ClientCallbackReaderWriterImpl(call, context, + reactor); + } +}; + +template +class ClientCallbackReaderImpl + : public ::grpc::experimental::ClientCallbackReader { + public: + // always allocated against a call arena, no memory free required + static void operator delete(void* ptr, std::size_t size) { + assert(size == sizeof(ClientCallbackReaderImpl)); + } + + // This operator should never be called as the memory should be freed as part + // of the arena destruction. It only exists to provide a matching operator + // delete to the operator new so that some compilers will not complain (see + // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this + // there are no tests catching the compiler warning. + static void operator delete(void*, void*) { assert(0); } + + void MaybeFinish() { + if (--callbacks_outstanding_ == 0) { + reactor_->OnDone(finish_status_); + auto* call = call_.call(); + this->~ClientCallbackReaderImpl(); + g_core_codegen_interface->grpc_call_unref(call); + } + } + + void StartCall() override { + // This call initiates two batches, plus any backlog, each with a callback + // 1. Send initial metadata (unless corked) + recv initial metadata + // 2. Any backlog + // 3. Recv trailing metadata, on_completion callback + started_ = true; + + start_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnReadInitialMetadataDone(ok); + MaybeFinish(); + }, + &start_ops_); + start_ops_.SendInitialMetadata(&context_->send_initial_metadata_, + context_->initial_metadata_flags()); + start_ops_.RecvInitialMetadata(context_); + start_ops_.set_core_cq_tag(&start_tag_); + call_.PerformOps(&start_ops_); + + // Also set up the read tag so it doesn't have to be set up each time + read_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnReadDone(ok); + MaybeFinish(); + }, + &read_ops_); + read_ops_.set_core_cq_tag(&read_tag_); + if (read_ops_at_start_) { + call_.PerformOps(&read_ops_); + } + + finish_tag_.Set(call_.call(), [this](bool ok) { MaybeFinish(); }, + &finish_ops_); + finish_ops_.ClientRecvStatus(context_, &finish_status_); + finish_ops_.set_core_cq_tag(&finish_tag_); + call_.PerformOps(&finish_ops_); + } + + void Read(Response* msg) override { + read_ops_.RecvMessage(msg); + callbacks_outstanding_++; + if (started_) { + call_.PerformOps(&read_ops_); + } else { + read_ops_at_start_ = true; + } + } + + private: + friend class ClientCallbackReaderFactory; + + template + ClientCallbackReaderImpl( + Call call, ClientContext* context, Request* request, + ::grpc::experimental::ClientReadReactor* reactor) + : context_(context), call_(call), reactor_(reactor) { + this->BindReactor(reactor); + // TODO(vjpai): don't assert + GPR_CODEGEN_ASSERT(start_ops_.SendMessage(*request).ok()); + start_ops_.ClientSendClose(); + } + + ClientContext* context_; + Call call_; + ::grpc::experimental::ClientReadReactor* reactor_; + + CallOpSet + start_ops_; + CallbackWithSuccessTag start_tag_; + + CallOpSet finish_ops_; + CallbackWithSuccessTag finish_tag_; + Status finish_status_; + + CallOpSet> read_ops_; + CallbackWithSuccessTag read_tag_; + bool read_ops_at_start_{false}; + + // Minimum of 2 outstanding callbacks to pre-register for start and finish + std::atomic_int callbacks_outstanding_{2}; + bool started_{false}; +}; + +template +class ClientCallbackReaderFactory { + public: + template + static void Create( + ChannelInterface* channel, const ::grpc::internal::RpcMethod& method, + ClientContext* context, const Request* request, + ::grpc::experimental::ClientReadReactor* reactor) { + Call call = channel->CreateCall(method, context, channel->CallbackCQ()); + + g_core_codegen_interface->grpc_call_ref(call.call()); + new (g_core_codegen_interface->grpc_call_arena_alloc( + call.call(), sizeof(ClientCallbackReaderImpl))) + ClientCallbackReaderImpl(call, context, request, reactor); + } +}; + +template +class ClientCallbackWriterImpl + : public ::grpc::experimental::ClientCallbackWriter { + public: + // always allocated against a call arena, no memory free required + static void operator delete(void* ptr, std::size_t size) { + assert(size == sizeof(ClientCallbackWriterImpl)); + } + + // This operator should never be called as the memory should be freed as part + // of the arena destruction. It only exists to provide a matching operator + // delete to the operator new so that some compilers will not complain (see + // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this + // there are no tests catching the compiler warning. + static void operator delete(void*, void*) { assert(0); } + + void MaybeFinish() { + if (--callbacks_outstanding_ == 0) { + reactor_->OnDone(finish_status_); + auto* call = call_.call(); + this->~ClientCallbackWriterImpl(); + g_core_codegen_interface->grpc_call_unref(call); + } + } + + void StartCall() override { + // This call initiates two batches, plus any backlog, each with a callback + // 1. Send initial metadata (unless corked) + recv initial metadata + // 2. Recv trailing metadata, on_completion callback + // 3. Any backlog + started_ = true; + + start_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnReadInitialMetadataDone(ok); + MaybeFinish(); + }, + &start_ops_); + if (!start_corked_) { + start_ops_.SendInitialMetadata(&context_->send_initial_metadata_, + context_->initial_metadata_flags()); + } + start_ops_.RecvInitialMetadata(context_); + start_ops_.set_core_cq_tag(&start_tag_); + call_.PerformOps(&start_ops_); + + // Also set up the read and write tags so that they don't have to be set up + // each time + write_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnWriteDone(ok); + MaybeFinish(); + }, + &write_ops_); + write_ops_.set_core_cq_tag(&write_tag_); + + finish_tag_.Set(call_.call(), [this](bool ok) { MaybeFinish(); }, + &finish_ops_); + finish_ops_.ClientRecvStatus(context_, &finish_status_); + finish_ops_.set_core_cq_tag(&finish_tag_); + call_.PerformOps(&finish_ops_); + + if (write_ops_at_start_) { + call_.PerformOps(&write_ops_); + } + + if (writes_done_ops_at_start_) { + call_.PerformOps(&writes_done_ops_); + } + } + + void Write(const Request* msg, WriteOptions options) override { + if (start_corked_) { + write_ops_.SendInitialMetadata(&context_->send_initial_metadata_, + context_->initial_metadata_flags()); + start_corked_ = false; + } + // TODO(vjpai): don't assert + GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok()); + + if (options.is_last_message()) { + options.set_buffer_hint(); + write_ops_.ClientSendClose(); + } + callbacks_outstanding_++; + if (started_) { + call_.PerformOps(&write_ops_); + } else { + write_ops_at_start_ = true; + } + } + void WritesDone() override { + if (start_corked_) { + writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_, + context_->initial_metadata_flags()); + start_corked_ = false; + } + writes_done_ops_.ClientSendClose(); + writes_done_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnWritesDoneDone(ok); + MaybeFinish(); + }, + &writes_done_ops_); + writes_done_ops_.set_core_cq_tag(&writes_done_tag_); + callbacks_outstanding_++; + if (started_) { + call_.PerformOps(&writes_done_ops_); + } else { + writes_done_ops_at_start_ = true; + } + } + + private: + friend class ClientCallbackWriterFactory; + + template + ClientCallbackWriterImpl( + Call call, ClientContext* context, Response* response, + ::grpc::experimental::ClientWriteReactor* reactor) + : context_(context), + call_(call), + reactor_(reactor), + start_corked_(context_->initial_metadata_corked_) { + this->BindReactor(reactor); + finish_ops_.RecvMessage(response); + finish_ops_.AllowNoMessage(); + } + + ClientContext* context_; + Call call_; + ::grpc::experimental::ClientWriteReactor* reactor_; + + CallOpSet start_ops_; + CallbackWithSuccessTag start_tag_; + bool start_corked_; + + CallOpSet finish_ops_; + CallbackWithSuccessTag finish_tag_; + Status finish_status_; + + CallOpSet + write_ops_; + CallbackWithSuccessTag write_tag_; + bool write_ops_at_start_{false}; + + CallOpSet writes_done_ops_; + CallbackWithSuccessTag writes_done_tag_; + bool writes_done_ops_at_start_{false}; + + // Minimum of 2 outstanding callbacks to pre-register for start and finish + std::atomic_int callbacks_outstanding_{2}; + bool started_{false}; +}; + +template +class ClientCallbackWriterFactory { + public: + template + static void Create( + ChannelInterface* channel, const ::grpc::internal::RpcMethod& method, + ClientContext* context, Response* response, + ::grpc::experimental::ClientWriteReactor* reactor) { + Call call = channel->CreateCall(method, context, channel->CallbackCQ()); + + g_core_codegen_interface->grpc_call_ref(call.call()); + new (g_core_codegen_interface->grpc_call_arena_alloc( + call.call(), sizeof(ClientCallbackWriterImpl))) + ClientCallbackWriterImpl(call, context, response, reactor); + } +}; } // namespace internal } // namespace grpc diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 75b955e7606..6059c3c58a4 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -71,6 +71,12 @@ template class BlockingUnaryCallImpl; template class CallbackUnaryCallImpl; +template +class ClientCallbackReaderWriterImpl; +template +class ClientCallbackReaderImpl; +template +class ClientCallbackWriterImpl; } // namespace internal template @@ -394,6 +400,12 @@ class ClientContext { friend class ::grpc::internal::BlockingUnaryCallImpl; template friend class ::grpc::internal::CallbackUnaryCallImpl; + template + friend class ::grpc::internal::ClientCallbackReaderWriterImpl; + template + friend class ::grpc::internal::ClientCallbackReaderImpl; + template + friend class ::grpc::internal::ClientCallbackWriterImpl; // Used by friend class CallOpClientRecvStatus void set_debug_error_string(const grpc::string& debug_error_string) { diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h index b866fc16dcf..1854f6ef2f5 100644 --- a/include/grpcpp/impl/codegen/server_callback.h +++ b/include/grpcpp/impl/codegen/server_callback.h @@ -19,7 +19,9 @@ #ifndef GRPCPP_IMPL_CODEGEN_SERVER_CALLBACK_H #define GRPCPP_IMPL_CODEGEN_SERVER_CALLBACK_H +#include #include +#include #include #include @@ -32,19 +34,33 @@ namespace grpc { -// forward declarations +// Declare base class of all reactors as internal namespace internal { -template -class CallbackUnaryHandler; + +class ServerReactor { + public: + virtual ~ServerReactor() = default; + virtual void OnDone() {} + virtual void OnCancel() {} +}; + } // namespace internal namespace experimental { +// Forward declarations +template +class ServerReadReactor; +template +class ServerWriteReactor; +template +class ServerBidiReactor; + // For unary RPCs, the exposed controller class is only an interface // and the actual implementation is an internal class. class ServerCallbackRpcController { public: - virtual ~ServerCallbackRpcController() {} + virtual ~ServerCallbackRpcController() = default; // The method handler must call this function when it is done so that // the library knows to free its resources @@ -55,18 +71,193 @@ class ServerCallbackRpcController { virtual void SendInitialMetadata(std::function) = 0; }; +// NOTE: The actual streaming object classes are provided +// as API only to support mocking. There are no implementations of +// these class interfaces in the API. +template +class ServerCallbackReader { + public: + virtual ~ServerCallbackReader() {} + virtual void Finish(Status s) = 0; + virtual void SendInitialMetadata() = 0; + virtual void Read(Request* msg) = 0; + + protected: + template + void BindReactor(ServerReadReactor* reactor) { + reactor->BindReader(this); + } +}; + +template +class ServerCallbackWriter { + public: + virtual ~ServerCallbackWriter() {} + + virtual void Finish(Status s) = 0; + virtual void SendInitialMetadata() = 0; + virtual void Write(const Response* msg, WriteOptions options) = 0; + virtual void WriteAndFinish(const Response* msg, WriteOptions options, + Status s) { + // Default implementation that can/should be overridden + Write(msg, std::move(options)); + Finish(std::move(s)); + }; + + protected: + template + void BindReactor(ServerWriteReactor* reactor) { + reactor->BindWriter(this); + } +}; + +template +class ServerCallbackReaderWriter { + public: + virtual ~ServerCallbackReaderWriter() {} + + virtual void Finish(Status s) = 0; + virtual void SendInitialMetadata() = 0; + virtual void Read(Request* msg) = 0; + virtual void Write(const Response* msg, WriteOptions options) = 0; + virtual void WriteAndFinish(const Response* msg, WriteOptions options, + Status s) { + // Default implementation that can/should be overridden + Write(msg, std::move(options)); + Finish(std::move(s)); + }; + + protected: + void BindReactor(ServerBidiReactor* reactor) { + reactor->BindStream(this); + } +}; + +// The following classes are reactors that are to be implemented +// by the user, returned as the result of the method handler for +// a callback method, and activated by the call to OnStarted +template +class ServerBidiReactor : public internal::ServerReactor { + public: + ~ServerBidiReactor() = default; + virtual void OnStarted(ServerContext*) {} + virtual void OnSendInitialMetadataDone(bool ok) {} + virtual void OnReadDone(bool ok) {} + virtual void OnWriteDone(bool ok) {} + + void StartSendInitialMetadata() { stream_->SendInitialMetadata(); } + void StartRead(Request* msg) { stream_->Read(msg); } + void StartWrite(const Response* msg) { StartWrite(msg, WriteOptions()); } + void StartWrite(const Response* msg, WriteOptions options) { + stream_->Write(msg, std::move(options)); + } + void StartWriteAndFinish(const Response* msg, WriteOptions options, + Status s) { + stream_->WriteAndFinish(msg, std::move(options), std::move(s)); + } + void StartWriteLast(const Response* msg, WriteOptions options) { + StartWrite(msg, std::move(options.set_last_message())); + } + void Finish(Status s) { stream_->Finish(std::move(s)); } + + private: + friend class ServerCallbackReaderWriter; + void BindStream(ServerCallbackReaderWriter* stream) { + stream_ = stream; + } + + ServerCallbackReaderWriter* stream_; +}; + +template +class ServerReadReactor : public internal::ServerReactor { + public: + ~ServerReadReactor() = default; + virtual void OnStarted(ServerContext*, Response* resp) {} + virtual void OnSendInitialMetadataDone(bool ok) {} + virtual void OnReadDone(bool ok) {} + + void StartSendInitialMetadata() { reader_->SendInitialMetadata(); } + void StartRead(Request* msg) { reader_->Read(msg); } + void Finish(Status s) { reader_->Finish(std::move(s)); } + + private: + friend class ServerCallbackReader; + void BindReader(ServerCallbackReader* reader) { reader_ = reader; } + + ServerCallbackReader* reader_; +}; + +template +class ServerWriteReactor : public internal::ServerReactor { + public: + ~ServerWriteReactor() = default; + virtual void OnStarted(ServerContext*, const Request* req) {} + virtual void OnSendInitialMetadataDone(bool ok) {} + virtual void OnWriteDone(bool ok) {} + + void StartSendInitialMetadata() { writer_->SendInitialMetadata(); } + void StartWrite(const Response* msg) { StartWrite(msg, WriteOptions()); } + void StartWrite(const Response* msg, WriteOptions options) { + writer_->Write(msg, std::move(options)); + } + void StartWriteAndFinish(const Response* msg, WriteOptions options, + Status s) { + writer_->WriteAndFinish(msg, std::move(options), std::move(s)); + } + void StartWriteLast(const Response* msg, WriteOptions options) { + StartWrite(msg, std::move(options.set_last_message())); + } + void Finish(Status s) { writer_->Finish(std::move(s)); } + + private: + friend class ServerCallbackWriter; + void BindWriter(ServerCallbackWriter* writer) { writer_ = writer; } + + ServerCallbackWriter* writer_; +}; + } // namespace experimental namespace internal { -template +template +class UnimplementedReadReactor + : public experimental::ServerReadReactor { + public: + void OnDone() override { delete this; } + void OnStarted(ServerContext*, Response*) override { + this->Finish(Status(StatusCode::UNIMPLEMENTED, "")); + } +}; + +template +class UnimplementedWriteReactor + : public experimental::ServerWriteReactor { + public: + void OnDone() override { delete this; } + void OnStarted(ServerContext*, const Request*) override { + this->Finish(Status(StatusCode::UNIMPLEMENTED, "")); + } +}; + +template +class UnimplementedBidiReactor + : public experimental::ServerBidiReactor { + public: + void OnDone() override { delete this; } + void OnStarted(ServerContext*) override { + this->Finish(Status(StatusCode::UNIMPLEMENTED, "")); + } +}; + +template class CallbackUnaryHandler : public MethodHandler { public: CallbackUnaryHandler( std::function - func, - ServiceType* service) + func) : func_(func) {} void RunHandler(const HandlerParameter& param) final { // Arena allocate a controller structure (that includes request/response) @@ -81,9 +272,8 @@ class CallbackUnaryHandler : public MethodHandler { if (status.ok()) { // Call the actual function handler and expect the user to call finish - CatchingCallback(std::move(func_), param.server_context, - controller->request(), controller->response(), - controller); + CatchingCallback(func_, param.server_context, controller->request(), + controller->response(), controller); } else { // if deserialization failed, we need to fail the call controller->Finish(status); @@ -117,79 +307,579 @@ class CallbackUnaryHandler : public MethodHandler { : public experimental::ServerCallbackRpcController { public: void Finish(Status s) override { - finish_tag_.Set( - call_.call(), - [this](bool) { - grpc_call* call = call_.call(); - auto call_requester = std::move(call_requester_); - this->~ServerCallbackRpcControllerImpl(); // explicitly call - // destructor - g_core_codegen_interface->grpc_call_unref(call); - call_requester(); - }, - &finish_buf_); + finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); }, + &finish_ops_); if (!ctx_->sent_initial_metadata_) { - finish_buf_.SendInitialMetadata(&ctx_->initial_metadata_, + finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { - finish_buf_.set_compression_level(ctx_->compression_level()); + finish_ops_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; } // The response is dropped if the status is not OK. if (s.ok()) { - finish_buf_.ServerSendStatus(&ctx_->trailing_metadata_, - finish_buf_.SendMessage(resp_)); + finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, + finish_ops_.SendMessage(resp_)); } else { - finish_buf_.ServerSendStatus(&ctx_->trailing_metadata_, s); + finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s); } - finish_buf_.set_core_cq_tag(&finish_tag_); - call_.PerformOps(&finish_buf_); + finish_ops_.set_core_cq_tag(&finish_tag_); + call_.PerformOps(&finish_ops_); } void SendInitialMetadata(std::function f) override { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); - - meta_tag_.Set(call_.call(), std::move(f), &meta_buf_); - meta_buf_.SendInitialMetadata(&ctx_->initial_metadata_, + callbacks_outstanding_++; + // TODO(vjpai): Consider taking f as a move-capture if we adopt C++14 + // and if performance of this operation matters + meta_tag_.Set(call_.call(), + [this, f](bool ok) { + f(ok); + MaybeDone(); + }, + &meta_ops_); + meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_, ctx_->initial_metadata_flags()); if (ctx_->compression_level_set()) { - meta_buf_.set_compression_level(ctx_->compression_level()); + meta_ops_.set_compression_level(ctx_->compression_level()); } ctx_->sent_initial_metadata_ = true; - meta_buf_.set_core_cq_tag(&meta_tag_); - call_.PerformOps(&meta_buf_); + meta_ops_.set_core_cq_tag(&meta_tag_); + call_.PerformOps(&meta_ops_); } private: - template - friend class CallbackUnaryHandler; + friend class CallbackUnaryHandler; ServerCallbackRpcControllerImpl(ServerContext* ctx, Call* call, - RequestType* req, + const RequestType* req, std::function call_requester) : ctx_(ctx), call_(*call), req_(req), - call_requester_(std::move(call_requester)) {} + call_requester_(std::move(call_requester)) { + ctx_->BeginCompletionOp(call, [this](bool) { MaybeDone(); }, nullptr); + } ~ServerCallbackRpcControllerImpl() { req_->~RequestType(); } - RequestType* request() { return req_; } + const RequestType* request() { return req_; } ResponseType* response() { return &resp_; } - CallOpSet meta_buf_; + void MaybeDone() { + if (--callbacks_outstanding_ == 0) { + grpc_call* call = call_.call(); + auto call_requester = std::move(call_requester_); + this->~ServerCallbackRpcControllerImpl(); // explicitly call destructor + g_core_codegen_interface->grpc_call_unref(call); + call_requester(); + } + } + + CallOpSet meta_ops_; CallbackWithSuccessTag meta_tag_; CallOpSet - finish_buf_; + finish_ops_; CallbackWithSuccessTag finish_tag_; ServerContext* ctx_; Call call_; - RequestType* req_; + const RequestType* req_; ResponseType resp_; std::function call_requester_; + std::atomic_int callbacks_outstanding_{ + 2}; // reserve for Finish and CompletionOp + }; +}; + +template +class CallbackClientStreamingHandler : public MethodHandler { + public: + CallbackClientStreamingHandler( + std::function< + experimental::ServerReadReactor*()> + func) + : func_(std::move(func)) {} + void RunHandler(const HandlerParameter& param) final { + // Arena allocate a reader structure (that includes response) + g_core_codegen_interface->grpc_call_ref(param.call->call()); + + experimental::ServerReadReactor* reactor = + param.status.ok() + ? CatchingReactorCreator< + experimental::ServerReadReactor>( + func_) + : nullptr; + + if (reactor == nullptr) { + // if deserialization or reactor creator failed, we need to fail the call + reactor = new UnimplementedReadReactor; + } + + auto* reader = new (g_core_codegen_interface->grpc_call_arena_alloc( + param.call->call(), sizeof(ServerCallbackReaderImpl))) + ServerCallbackReaderImpl(param.server_context, param.call, + std::move(param.call_requester), reactor); + + reader->BindReactor(reactor); + reactor->OnStarted(param.server_context, reader->response()); + reader->MaybeDone(); + } + + private: + std::function*()> + func_; + + class ServerCallbackReaderImpl + : public experimental::ServerCallbackReader { + public: + void Finish(Status s) override { + finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); }, + &finish_ops_); + if (!ctx_->sent_initial_metadata_) { + finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); + if (ctx_->compression_level_set()) { + finish_ops_.set_compression_level(ctx_->compression_level()); + } + ctx_->sent_initial_metadata_ = true; + } + // The response is dropped if the status is not OK. + if (s.ok()) { + finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, + finish_ops_.SendMessage(resp_)); + } else { + finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s); + } + finish_ops_.set_core_cq_tag(&finish_tag_); + call_.PerformOps(&finish_ops_); + } + + void SendInitialMetadata() override { + GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); + callbacks_outstanding_++; + meta_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnSendInitialMetadataDone(ok); + MaybeDone(); + }, + &meta_ops_); + meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); + if (ctx_->compression_level_set()) { + meta_ops_.set_compression_level(ctx_->compression_level()); + } + ctx_->sent_initial_metadata_ = true; + meta_ops_.set_core_cq_tag(&meta_tag_); + call_.PerformOps(&meta_ops_); + } + + void Read(RequestType* req) override { + callbacks_outstanding_++; + read_ops_.RecvMessage(req); + call_.PerformOps(&read_ops_); + } + + private: + friend class CallbackClientStreamingHandler; + + ServerCallbackReaderImpl( + ServerContext* ctx, Call* call, std::function call_requester, + experimental::ServerReadReactor* reactor) + : ctx_(ctx), + call_(*call), + call_requester_(std::move(call_requester)), + reactor_(reactor) { + ctx_->BeginCompletionOp(call, [this](bool) { MaybeDone(); }, reactor); + read_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnReadDone(ok); + MaybeDone(); + }, + &read_ops_); + read_ops_.set_core_cq_tag(&read_tag_); + } + + ~ServerCallbackReaderImpl() {} + + ResponseType* response() { return &resp_; } + + void MaybeDone() { + if (--callbacks_outstanding_ == 0) { + reactor_->OnDone(); + grpc_call* call = call_.call(); + auto call_requester = std::move(call_requester_); + this->~ServerCallbackReaderImpl(); // explicitly call destructor + g_core_codegen_interface->grpc_call_unref(call); + call_requester(); + } + } + + CallOpSet meta_ops_; + CallbackWithSuccessTag meta_tag_; + CallOpSet + finish_ops_; + CallbackWithSuccessTag finish_tag_; + CallOpSet> read_ops_; + CallbackWithSuccessTag read_tag_; + + ServerContext* ctx_; + Call call_; + ResponseType resp_; + std::function call_requester_; + experimental::ServerReadReactor* reactor_; + std::atomic_int callbacks_outstanding_{ + 3}; // reserve for OnStarted, Finish, and CompletionOp + }; +}; + +template +class CallbackServerStreamingHandler : public MethodHandler { + public: + CallbackServerStreamingHandler( + std::function< + experimental::ServerWriteReactor*()> + func) + : func_(std::move(func)) {} + void RunHandler(const HandlerParameter& param) final { + // Arena allocate a writer structure + g_core_codegen_interface->grpc_call_ref(param.call->call()); + + experimental::ServerWriteReactor* reactor = + param.status.ok() + ? CatchingReactorCreator< + experimental::ServerWriteReactor>( + func_) + : nullptr; + + if (reactor == nullptr) { + // if deserialization or reactor creator failed, we need to fail the call + reactor = new UnimplementedWriteReactor; + } + + auto* writer = new (g_core_codegen_interface->grpc_call_arena_alloc( + param.call->call(), sizeof(ServerCallbackWriterImpl))) + ServerCallbackWriterImpl(param.server_context, param.call, + static_cast(param.request), + std::move(param.call_requester), reactor); + writer->BindReactor(reactor); + reactor->OnStarted(param.server_context, writer->request()); + writer->MaybeDone(); + } + + void* Deserialize(grpc_call* call, grpc_byte_buffer* req, + Status* status) final { + ByteBuffer buf; + buf.set_buffer(req); + auto* request = new (g_core_codegen_interface->grpc_call_arena_alloc( + call, sizeof(RequestType))) RequestType(); + *status = SerializationTraits::Deserialize(&buf, request); + buf.Release(); + if (status->ok()) { + return request; + } + request->~RequestType(); + return nullptr; + } + + private: + std::function*()> + func_; + + class ServerCallbackWriterImpl + : public experimental::ServerCallbackWriter { + public: + void Finish(Status s) override { + finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); }, + &finish_ops_); + finish_ops_.set_core_cq_tag(&finish_tag_); + + if (!ctx_->sent_initial_metadata_) { + finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); + if (ctx_->compression_level_set()) { + finish_ops_.set_compression_level(ctx_->compression_level()); + } + ctx_->sent_initial_metadata_ = true; + } + finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s); + call_.PerformOps(&finish_ops_); + } + + void SendInitialMetadata() override { + GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); + callbacks_outstanding_++; + meta_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnSendInitialMetadataDone(ok); + MaybeDone(); + }, + &meta_ops_); + meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); + if (ctx_->compression_level_set()) { + meta_ops_.set_compression_level(ctx_->compression_level()); + } + ctx_->sent_initial_metadata_ = true; + meta_ops_.set_core_cq_tag(&meta_tag_); + call_.PerformOps(&meta_ops_); + } + + void Write(const ResponseType* resp, WriteOptions options) override { + callbacks_outstanding_++; + if (options.is_last_message()) { + options.set_buffer_hint(); + } + if (!ctx_->sent_initial_metadata_) { + write_ops_.SendInitialMetadata(&ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); + if (ctx_->compression_level_set()) { + write_ops_.set_compression_level(ctx_->compression_level()); + } + ctx_->sent_initial_metadata_ = true; + } + // TODO(vjpai): don't assert + GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok()); + call_.PerformOps(&write_ops_); + } + + void WriteAndFinish(const ResponseType* resp, WriteOptions options, + Status s) override { + // This combines the write into the finish callback + // Don't send any message if the status is bad + if (s.ok()) { + // TODO(vjpai): don't assert + GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok()); + } + Finish(std::move(s)); + } + + private: + friend class CallbackServerStreamingHandler; + + ServerCallbackWriterImpl( + ServerContext* ctx, Call* call, const RequestType* req, + std::function call_requester, + experimental::ServerWriteReactor* reactor) + : ctx_(ctx), + call_(*call), + req_(req), + call_requester_(std::move(call_requester)), + reactor_(reactor) { + ctx_->BeginCompletionOp(call, [this](bool) { MaybeDone(); }, reactor); + write_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnWriteDone(ok); + MaybeDone(); + }, + &write_ops_); + write_ops_.set_core_cq_tag(&write_tag_); + } + ~ServerCallbackWriterImpl() { req_->~RequestType(); } + + const RequestType* request() { return req_; } + + void MaybeDone() { + if (--callbacks_outstanding_ == 0) { + reactor_->OnDone(); + grpc_call* call = call_.call(); + auto call_requester = std::move(call_requester_); + this->~ServerCallbackWriterImpl(); // explicitly call destructor + g_core_codegen_interface->grpc_call_unref(call); + call_requester(); + } + } + + CallOpSet meta_ops_; + CallbackWithSuccessTag meta_tag_; + CallOpSet + finish_ops_; + CallbackWithSuccessTag finish_tag_; + CallOpSet write_ops_; + CallbackWithSuccessTag write_tag_; + + ServerContext* ctx_; + Call call_; + const RequestType* req_; + std::function call_requester_; + experimental::ServerWriteReactor* reactor_; + std::atomic_int callbacks_outstanding_{ + 3}; // reserve for OnStarted, Finish, and CompletionOp + }; +}; + +template +class CallbackBidiHandler : public MethodHandler { + public: + CallbackBidiHandler( + std::function< + experimental::ServerBidiReactor*()> + func) + : func_(std::move(func)) {} + void RunHandler(const HandlerParameter& param) final { + g_core_codegen_interface->grpc_call_ref(param.call->call()); + + experimental::ServerBidiReactor* reactor = + param.status.ok() + ? CatchingReactorCreator< + experimental::ServerBidiReactor>( + func_) + : nullptr; + + if (reactor == nullptr) { + // if deserialization or reactor creator failed, we need to fail the call + reactor = new UnimplementedBidiReactor; + } + + auto* stream = new (g_core_codegen_interface->grpc_call_arena_alloc( + param.call->call(), sizeof(ServerCallbackReaderWriterImpl))) + ServerCallbackReaderWriterImpl(param.server_context, param.call, + std::move(param.call_requester), + reactor); + + stream->BindReactor(reactor); + reactor->OnStarted(param.server_context); + stream->MaybeDone(); + } + + private: + std::function*()> + func_; + + class ServerCallbackReaderWriterImpl + : public experimental::ServerCallbackReaderWriter { + public: + void Finish(Status s) override { + finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); }, + &finish_ops_); + finish_ops_.set_core_cq_tag(&finish_tag_); + + if (!ctx_->sent_initial_metadata_) { + finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); + if (ctx_->compression_level_set()) { + finish_ops_.set_compression_level(ctx_->compression_level()); + } + ctx_->sent_initial_metadata_ = true; + } + finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s); + call_.PerformOps(&finish_ops_); + } + + void SendInitialMetadata() override { + GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); + callbacks_outstanding_++; + meta_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnSendInitialMetadataDone(ok); + MaybeDone(); + }, + &meta_ops_); + meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); + if (ctx_->compression_level_set()) { + meta_ops_.set_compression_level(ctx_->compression_level()); + } + ctx_->sent_initial_metadata_ = true; + meta_ops_.set_core_cq_tag(&meta_tag_); + call_.PerformOps(&meta_ops_); + } + + void Write(const ResponseType* resp, WriteOptions options) override { + callbacks_outstanding_++; + if (options.is_last_message()) { + options.set_buffer_hint(); + } + if (!ctx_->sent_initial_metadata_) { + write_ops_.SendInitialMetadata(&ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); + if (ctx_->compression_level_set()) { + write_ops_.set_compression_level(ctx_->compression_level()); + } + ctx_->sent_initial_metadata_ = true; + } + // TODO(vjpai): don't assert + GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok()); + call_.PerformOps(&write_ops_); + } + + void WriteAndFinish(const ResponseType* resp, WriteOptions options, + Status s) override { + // Don't send any message if the status is bad + if (s.ok()) { + // TODO(vjpai): don't assert + GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok()); + } + Finish(std::move(s)); + } + + void Read(RequestType* req) override { + callbacks_outstanding_++; + read_ops_.RecvMessage(req); + call_.PerformOps(&read_ops_); + } + + private: + friend class CallbackBidiHandler; + + ServerCallbackReaderWriterImpl( + ServerContext* ctx, Call* call, std::function call_requester, + experimental::ServerBidiReactor* reactor) + : ctx_(ctx), + call_(*call), + call_requester_(std::move(call_requester)), + reactor_(reactor) { + ctx_->BeginCompletionOp(call, [this](bool) { MaybeDone(); }, reactor); + write_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnWriteDone(ok); + MaybeDone(); + }, + &write_ops_); + write_ops_.set_core_cq_tag(&write_tag_); + read_tag_.Set(call_.call(), + [this](bool ok) { + reactor_->OnReadDone(ok); + MaybeDone(); + }, + &read_ops_); + read_ops_.set_core_cq_tag(&read_tag_); + } + ~ServerCallbackReaderWriterImpl() {} + + void MaybeDone() { + if (--callbacks_outstanding_ == 0) { + reactor_->OnDone(); + grpc_call* call = call_.call(); + auto call_requester = std::move(call_requester_); + this->~ServerCallbackReaderWriterImpl(); // explicitly call destructor + g_core_codegen_interface->grpc_call_unref(call); + call_requester(); + } + } + + CallOpSet meta_ops_; + CallbackWithSuccessTag meta_tag_; + CallOpSet + finish_ops_; + CallbackWithSuccessTag finish_tag_; + CallOpSet write_ops_; + CallbackWithSuccessTag write_tag_; + CallOpSet> read_ops_; + CallbackWithSuccessTag read_tag_; + + ServerContext* ctx_; + Call call_; + std::function call_requester_; + experimental::ServerBidiReactor* reactor_; + std::atomic_int callbacks_outstanding_{ + 3}; // reserve for OnStarted, Finish, and CompletionOp }; }; diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h index 82ee862f61b..4a5f9e2dd91 100644 --- a/include/grpcpp/impl/codegen/server_context.h +++ b/include/grpcpp/impl/codegen/server_context.h @@ -66,13 +66,20 @@ template class ServerStreamingHandler; template class BidiStreamingHandler; -template +template class CallbackUnaryHandler; +template +class CallbackClientStreamingHandler; +template +class CallbackServerStreamingHandler; +template +class CallbackBidiHandler; template class TemplatedBidiStreamingHandler; template class ErrorMethodHandler; class Call; +class ServerReactor; } // namespace internal class CompletionQueue; @@ -270,8 +277,14 @@ class ServerContext { friend class ::grpc::internal::ServerStreamingHandler; template friend class ::grpc::internal::TemplatedBidiStreamingHandler; - template + template friend class ::grpc::internal::CallbackUnaryHandler; + template + friend class ::grpc::internal::CallbackClientStreamingHandler; + template + friend class ::grpc::internal::CallbackServerStreamingHandler; + template + friend class ::grpc::internal::CallbackBidiHandler; template friend class internal::ErrorMethodHandler; friend class ::grpc::ClientContext; @@ -282,7 +295,9 @@ class ServerContext { class CompletionOp; - void BeginCompletionOp(internal::Call* call, bool callback); + void BeginCompletionOp(internal::Call* call, + std::function callback, + internal::ServerReactor* reactor); /// Return the tag queued by BeginCompletionOp() internal::CompletionQueueTag* GetCompletionOpTag(); diff --git a/setup.py b/setup.py index ae86e6c9fb7..7bdfc99e24b 100644 --- a/setup.py +++ b/setup.py @@ -87,6 +87,7 @@ CLASSIFIERS = [ # present, then it will still attempt to use Cython. BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False) + # Export this variable to use the system installation of openssl. You need to # have the header files installed (in /usr/include/openssl) and during # runtime, the shared library must be installed @@ -105,6 +106,21 @@ BUILD_WITH_SYSTEM_ZLIB = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_ZLIB', BUILD_WITH_SYSTEM_CARES = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_CARES', False) +# For local development use only: This skips building gRPC Core and its +# dependencies, including protobuf and boringssl. This allows "incremental" +# compilation by first building gRPC Core using make, then building only the +# Python/Cython layers here. +# +# Note that this requires libboringssl.a in the libs/{dbg,opt}/ directory, which +# may require configuring make to not use the system openssl implementation: +# +# make HAS_SYSTEM_OPENSSL_ALPN=0 +# +# TODO(ericgribkoff) Respect the BUILD_WITH_SYSTEM_* flags alongside this option +USE_PREBUILT_GRPC_CORE = os.environ.get( + 'GRPC_PYTHON_USE_PREBUILT_GRPC_CORE', False) + + # If this environmental variable is set, GRPC will not try to be compatible with # libc versions old than the one it was compiled against. DISABLE_LIBC_COMPATIBILITY = os.environ.get('GRPC_PYTHON_DISABLE_LIBC_COMPATIBILITY', False) @@ -249,7 +265,7 @@ def cython_extensions_and_necessity(): for name in CYTHON_EXTENSION_MODULE_NAMES] config = os.environ.get('CONFIG', 'opt') prefix = 'libs/' + config + '/' - if "darwin" in sys.platform: + if "darwin" in sys.platform or USE_PREBUILT_GRPC_CORE: extra_objects = [prefix + 'libares.a', prefix + 'libboringssl.a', prefix + 'libgpr.a', diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index 7986aca6960..b0046872502 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -132,6 +132,7 @@ grpc::string GetHeaderIncludes(grpc_generator::File* file, "grpcpp/impl/codegen/async_generic_service.h", "grpcpp/impl/codegen/async_stream.h", "grpcpp/impl/codegen/async_unary_call.h", + "grpcpp/impl/codegen/client_callback.h", "grpcpp/impl/codegen/method_handler_impl.h", "grpcpp/impl/codegen/proto_utils.h", "grpcpp/impl/codegen/rpc_method.h", @@ -580,11 +581,22 @@ void PrintHeaderClientMethodCallbackInterfaces( "const $Request$* request, $Response$* response, " "std::function) = 0;\n"); } else if (ClientOnlyStreaming(method)) { - // TODO(vjpai): Add support for client-side streaming + printer->Print(*vars, + "virtual void $Method$(::grpc::ClientContext* context, " + "$Response$* response, " + "::grpc::experimental::ClientWriteReactor< $Request$>* " + "reactor) = 0;\n"); } else if (ServerOnlyStreaming(method)) { - // TODO(vjpai): Add support for server-side streaming + printer->Print(*vars, + "virtual void $Method$(::grpc::ClientContext* context, " + "$Request$* request, " + "::grpc::experimental::ClientReadReactor< $Response$>* " + "reactor) = 0;\n"); } else if (method->BidiStreaming()) { - // TODO(vjpai): Add support for bidi streaming + printer->Print(*vars, + "virtual void $Method$(::grpc::ClientContext* context, " + "::grpc::experimental::ClientBidiReactor< " + "$Request$,$Response$>* reactor) = 0;\n"); } } @@ -631,11 +643,23 @@ void PrintHeaderClientMethodCallback(grpc_generator::Printer* printer, "const $Request$* request, $Response$* response, " "std::function) override;\n"); } else if (ClientOnlyStreaming(method)) { - // TODO(vjpai): Add support for client-side streaming + printer->Print(*vars, + "void $Method$(::grpc::ClientContext* context, " + "$Response$* response, " + "::grpc::experimental::ClientWriteReactor< $Request$>* " + "reactor) override;\n"); } else if (ServerOnlyStreaming(method)) { - // TODO(vjpai): Add support for server-side streaming + printer->Print(*vars, + "void $Method$(::grpc::ClientContext* context, " + "$Request$* request, " + "::grpc::experimental::ClientReadReactor< $Response$>* " + "reactor) override;\n"); + } else if (method->BidiStreaming()) { - // TODO(vjpai): Add support for bidi streaming + printer->Print(*vars, + "void $Method$(::grpc::ClientContext* context, " + "::grpc::experimental::ClientBidiReactor< " + "$Request$,$Response$>* reactor) override;\n"); } } @@ -865,6 +889,11 @@ void PrintHeaderServerCallbackMethodsHelper( " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); + printer->Print(*vars, + "virtual ::grpc::experimental::ServerReadReactor< " + "$RealRequest$, $RealResponse$>* $Method$() {\n" + " return new ::grpc::internal::UnimplementedReadReactor<\n" + " $RealRequest$, $RealResponse$>;}\n"); } else if (ServerOnlyStreaming(method)) { printer->Print( *vars, @@ -876,6 +905,11 @@ void PrintHeaderServerCallbackMethodsHelper( " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); + printer->Print(*vars, + "virtual ::grpc::experimental::ServerWriteReactor< " + "$RealRequest$, $RealResponse$>* $Method$() {\n" + " return new ::grpc::internal::UnimplementedWriteReactor<\n" + " $RealRequest$, $RealResponse$>;}\n"); } else if (method->BidiStreaming()) { printer->Print( *vars, @@ -887,6 +921,11 @@ void PrintHeaderServerCallbackMethodsHelper( " abort();\n" " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" "}\n"); + printer->Print(*vars, + "virtual ::grpc::experimental::ServerBidiReactor< " + "$RealRequest$, $RealResponse$>* $Method$() {\n" + " return new ::grpc::internal::UnimplementedBidiReactor<\n" + " $RealRequest$, $RealResponse$>;}\n"); } } @@ -915,22 +954,36 @@ void PrintHeaderServerMethodCallback( *vars, " ::grpc::Service::experimental().MarkMethodCallback($Idx$,\n" " new ::grpc::internal::CallbackUnaryHandler< " - "ExperimentalWithCallbackMethod_$Method$, $RealRequest$, " - "$RealResponse$>(\n" + "$RealRequest$, $RealResponse$>(\n" " [this](::grpc::ServerContext* context,\n" " const $RealRequest$* request,\n" " $RealResponse$* response,\n" " ::grpc::experimental::ServerCallbackRpcController* " "controller) {\n" - " this->$" + " return this->$" "Method$(context, request, response, controller);\n" - " }, this));\n"); + " }));\n"); } else if (ClientOnlyStreaming(method)) { - // TODO(vjpai): Add in code generation for all streaming methods + printer->Print( + *vars, + " ::grpc::Service::experimental().MarkMethodCallback($Idx$,\n" + " new ::grpc::internal::CallbackClientStreamingHandler< " + "$RealRequest$, $RealResponse$>(\n" + " [this] { return this->$Method$(); }));\n"); } else if (ServerOnlyStreaming(method)) { - // TODO(vjpai): Add in code generation for all streaming methods + printer->Print( + *vars, + " ::grpc::Service::experimental().MarkMethodCallback($Idx$,\n" + " new ::grpc::internal::CallbackServerStreamingHandler< " + "$RealRequest$, $RealResponse$>(\n" + " [this] { return this->$Method$(); }));\n"); } else if (method->BidiStreaming()) { - // TODO(vjpai): Add in code generation for all streaming methods + printer->Print( + *vars, + " ::grpc::Service::experimental().MarkMethodCallback($Idx$,\n" + " new ::grpc::internal::CallbackBidiHandler< " + "$RealRequest$, $RealResponse$>(\n" + " [this] { return this->$Method$(); }));\n"); } printer->Print(*vars, "}\n"); printer->Print(*vars, @@ -967,8 +1020,7 @@ void PrintHeaderServerMethodRawCallback( *vars, " ::grpc::Service::experimental().MarkMethodRawCallback($Idx$,\n" " new ::grpc::internal::CallbackUnaryHandler< " - "ExperimentalWithRawCallbackMethod_$Method$, $RealRequest$, " - "$RealResponse$>(\n" + "$RealRequest$, $RealResponse$>(\n" " [this](::grpc::ServerContext* context,\n" " const $RealRequest$* request,\n" " $RealResponse$* response,\n" @@ -976,13 +1028,28 @@ void PrintHeaderServerMethodRawCallback( "controller) {\n" " this->$" "Method$(context, request, response, controller);\n" - " }, this));\n"); + " }));\n"); } else if (ClientOnlyStreaming(method)) { - // TODO(vjpai): Add in code generation for all streaming methods + printer->Print( + *vars, + " ::grpc::Service::experimental().MarkMethodRawCallback($Idx$,\n" + " new ::grpc::internal::CallbackClientStreamingHandler< " + "$RealRequest$, $RealResponse$>(\n" + " [this] { return this->$Method$(); }));\n"); } else if (ServerOnlyStreaming(method)) { - // TODO(vjpai): Add in code generation for all streaming methods + printer->Print( + *vars, + " ::grpc::Service::experimental().MarkMethodRawCallback($Idx$,\n" + " new ::grpc::internal::CallbackServerStreamingHandler< " + "$RealRequest$, $RealResponse$>(\n" + " [this] { return this->$Method$(); }));\n"); } else if (method->BidiStreaming()) { - // TODO(vjpai): Add in code generation for all streaming methods + printer->Print( + *vars, + " ::grpc::Service::experimental().MarkMethodRawCallback($Idx$,\n" + " new ::grpc::internal::CallbackBidiHandler< " + "$RealRequest$, $RealResponse$>(\n" + " [this] { return this->$Method$(); }));\n"); } printer->Print(*vars, "}\n"); printer->Print(*vars, @@ -1607,7 +1674,19 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer, "context, response);\n" "}\n\n"); - // TODO(vjpai): Add callback version + printer->Print( + *vars, + "void $ns$$Service$::" + "Stub::experimental_async::$Method$(::grpc::ClientContext* context, " + "$Response$* response, " + "::grpc::experimental::ClientWriteReactor< $Request$>* reactor) {\n"); + printer->Print(*vars, + " ::grpc::internal::ClientCallbackWriterFactory< " + "$Request$>::Create(" + "stub_->channel_.get(), " + "stub_->rpcmethod_$Method$_, " + "context, response, reactor);\n" + "}\n\n"); for (auto async_prefix : async_prefixes) { (*vars)["AsyncPrefix"] = async_prefix.prefix; @@ -1641,7 +1720,19 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer, "context, request);\n" "}\n\n"); - // TODO(vjpai): Add callback version + printer->Print( + *vars, + "void $ns$$Service$::Stub::experimental_async::$Method$(::grpc::" + "ClientContext* context, " + "$Request$* request, " + "::grpc::experimental::ClientReadReactor< $Response$>* reactor) {\n"); + printer->Print(*vars, + " ::grpc::internal::ClientCallbackReaderFactory< " + "$Response$>::Create(" + "stub_->channel_.get(), " + "stub_->rpcmethod_$Method$_, " + "context, request, reactor);\n" + "}\n\n"); for (auto async_prefix : async_prefixes) { (*vars)["AsyncPrefix"] = async_prefix.prefix; @@ -1675,7 +1766,19 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer, "context);\n" "}\n\n"); - // TODO(vjpai): Add callback version + printer->Print( + *vars, + "void $ns$$Service$::Stub::experimental_async::$Method$(::grpc::" + "ClientContext* context, " + "::grpc::experimental::ClientBidiReactor< $Request$,$Response$>* " + "reactor) {\n"); + printer->Print(*vars, + " ::grpc::internal::ClientCallbackReaderWriterFactory< " + "$Request$,$Response$>::Create(" + "stub_->channel_.get(), " + "stub_->rpcmethod_$Method$_, " + "context, reactor);\n" + "}\n\n"); for (auto async_prefix : async_prefixes) { (*vars)["AsyncPrefix"] = async_prefix.prefix; diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index dc0e1f89ce6..7e70f1c28bd 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -749,7 +749,7 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked( void* arg, grpc_error* error) { BalancerCallState* lb_calld = static_cast(arg); GrpcLb* grpclb_policy = lb_calld->grpclb_policy(); - // Empty payload means the LB call was cancelled. + // Null payload means the LB call was cancelled. if (lb_calld != grpclb_policy->lb_calld_.get() || lb_calld->recv_message_payload_ == nullptr) { lb_calld->Unref(DEBUG_LOCATION, "on_message_received"); @@ -803,54 +803,45 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked( gpr_free(ipport); } } - /* update serverlist */ - if (serverlist->num_servers > 0) { - // Start sending client load report only after we start using the - // serverlist returned from the current LB call. - if (lb_calld->client_stats_report_interval_ > 0 && - lb_calld->client_stats_ == nullptr) { - lb_calld->client_stats_.reset(New()); - // TODO(roth): We currently track this ref manually. Once the - // ClosureRef API is ready, we should pass the RefCountedPtr<> along - // with the callback. - auto self = lb_calld->Ref(DEBUG_LOCATION, "client_load_report"); - self.release(); - lb_calld->ScheduleNextClientLoadReportLocked(); - } - if (grpc_grpclb_serverlist_equals(grpclb_policy->serverlist_, - serverlist)) { - if (grpc_lb_glb_trace.enabled()) { - gpr_log(GPR_INFO, - "[grpclb %p] Incoming server list identical to current, " - "ignoring.", - grpclb_policy); - } - grpc_grpclb_destroy_serverlist(serverlist); - } else { /* new serverlist */ - if (grpclb_policy->serverlist_ != nullptr) { - /* dispose of the old serverlist */ - grpc_grpclb_destroy_serverlist(grpclb_policy->serverlist_); - } else { - /* or dispose of the fallback */ - grpc_lb_addresses_destroy(grpclb_policy->fallback_backend_addresses_); - grpclb_policy->fallback_backend_addresses_ = nullptr; - if (grpclb_policy->fallback_timer_callback_pending_) { - grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_); - } - } - // and update the copy in the GrpcLb instance. This - // serverlist instance will be destroyed either upon the next - // update or when the GrpcLb instance is destroyed. - grpclb_policy->serverlist_ = serverlist; - grpclb_policy->serverlist_index_ = 0; - grpclb_policy->CreateOrUpdateRoundRobinPolicyLocked(); - } - } else { + // Start sending client load report only after we start using the + // serverlist returned from the current LB call. + if (lb_calld->client_stats_report_interval_ > 0 && + lb_calld->client_stats_ == nullptr) { + lb_calld->client_stats_.reset(New()); + // TODO(roth): We currently track this ref manually. Once the + // ClosureRef API is ready, we should pass the RefCountedPtr<> along + // with the callback. + auto self = lb_calld->Ref(DEBUG_LOCATION, "client_load_report"); + self.release(); + lb_calld->ScheduleNextClientLoadReportLocked(); + } + // Check if the serverlist differs from the previous one. + if (grpc_grpclb_serverlist_equals(grpclb_policy->serverlist_, serverlist)) { if (grpc_lb_glb_trace.enabled()) { - gpr_log(GPR_INFO, "[grpclb %p] Received empty server list, ignoring.", + gpr_log(GPR_INFO, + "[grpclb %p] Incoming server list identical to current, " + "ignoring.", grpclb_policy); } grpc_grpclb_destroy_serverlist(serverlist); + } else { // New serverlist. + if (grpclb_policy->serverlist_ != nullptr) { + // Dispose of the old serverlist. + grpc_grpclb_destroy_serverlist(grpclb_policy->serverlist_); + } else { + // Dispose of the fallback. + grpc_lb_addresses_destroy(grpclb_policy->fallback_backend_addresses_); + grpclb_policy->fallback_backend_addresses_ = nullptr; + if (grpclb_policy->fallback_timer_callback_pending_) { + grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_); + } + } + // Update the serverlist in the GrpcLb instance. This serverlist + // instance will be destroyed either upon the next update or when the + // GrpcLb instance is destroyed. + grpclb_policy->serverlist_ = serverlist; + grpclb_policy->serverlist_index_ = 0; + grpclb_policy->CreateOrUpdateRoundRobinPolicyLocked(); } } else { // No valid initial response or serverlist found. @@ -1583,7 +1574,7 @@ void GrpcLb::AddPendingPick(PendingPick* pp) { bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp, grpc_error** error) { // Check for drops if we are not using fallback backend addresses. - if (serverlist_ != nullptr) { + if (serverlist_ != nullptr && serverlist_->num_servers > 0) { // Look at the index into the serverlist to see if we should drop this call. grpc_grpclb_server* server = serverlist_->servers[serverlist_index_++]; if (serverlist_index_ == serverlist_->num_servers) { @@ -1681,7 +1672,6 @@ grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() { grpc_lb_addresses* addresses; bool is_backend_from_grpclb_load_balancer = false; if (serverlist_ != nullptr) { - GPR_ASSERT(serverlist_->num_servers > 0); addresses = ProcessServerlist(serverlist_); is_backend_from_grpclb_load_balancer = true; } else { diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 90bc88961d9..4ebc2c8161c 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -122,6 +122,8 @@ class AresDnsResolver : public Resolver { char* service_config_json_ = nullptr; // has shutdown been initiated bool shutdown_initiated_ = false; + // timeout in milliseconds for active DNS queries + int query_timeout_ms_; }; AresDnsResolver::AresDnsResolver(const ResolverArgs& args) @@ -159,6 +161,11 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args) grpc_combiner_scheduler(combiner())); GRPC_CLOSURE_INIT(&on_resolved_, OnResolvedLocked, this, grpc_combiner_scheduler(combiner())); + const grpc_arg* query_timeout_ms_arg = + grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS); + query_timeout_ms_ = grpc_channel_arg_get_integer( + query_timeout_ms_arg, + {GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS, 0, INT_MAX}); } AresDnsResolver::~AresDnsResolver() { @@ -410,7 +417,8 @@ void AresDnsResolver::StartResolvingLocked() { pending_request_ = grpc_dns_lookup_ares_locked( dns_server_, name_to_resolve_, kDefaultPort, interested_parties_, &on_resolved_, &lb_addresses_, true /* check_grpclb */, - request_service_config_ ? &service_config_json_ : nullptr, combiner()); + request_service_config_ ? &service_config_json_ : nullptr, + query_timeout_ms_, combiner()); last_resolution_timestamp_ = grpc_core::ExecCtx::Get()->Now(); } diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc index fdbd07ebf51..f42b1e309df 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc @@ -33,6 +33,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/timer.h" typedef struct fd_node { /** the owner of this fd node */ @@ -76,6 +77,12 @@ struct grpc_ares_ev_driver { grpc_ares_request* request; /** Owned by the ev_driver. Creates new GrpcPolledFd's */ grpc_core::UniquePtr polled_fd_factory; + /** query timeout in milliseconds */ + int query_timeout_ms; + /** alarm to cancel active queries */ + grpc_timer query_timeout; + /** cancels queries on a timeout */ + grpc_closure on_timeout_locked; }; static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver); @@ -116,8 +123,11 @@ static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) { } } +static void on_timeout_locked(void* arg, grpc_error* error); + grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver, grpc_pollset_set* pollset_set, + int query_timeout_ms, grpc_combiner* combiner, grpc_ares_request* request) { *ev_driver = grpc_core::New(); @@ -146,6 +156,9 @@ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver, grpc_core::NewGrpcPolledFdFactory((*ev_driver)->combiner); (*ev_driver) ->polled_fd_factory->ConfigureAresChannelLocked((*ev_driver)->channel); + GRPC_CLOSURE_INIT(&(*ev_driver)->on_timeout_locked, on_timeout_locked, + *ev_driver, grpc_combiner_scheduler(combiner)); + (*ev_driver)->query_timeout_ms = query_timeout_ms; return GRPC_ERROR_NONE; } @@ -155,6 +168,7 @@ void grpc_ares_ev_driver_on_queries_complete_locked( // is working, grpc_ares_notify_on_event_locked will shut down the // fds; if it's not working, there are no fds to shut down. ev_driver->shutting_down = true; + grpc_timer_cancel(&ev_driver->query_timeout); grpc_ares_ev_driver_unref(ev_driver); } @@ -185,6 +199,17 @@ static fd_node* pop_fd_node_locked(fd_node** head, ares_socket_t as) { return nullptr; } +static void on_timeout_locked(void* arg, grpc_error* error) { + grpc_ares_ev_driver* driver = static_cast(arg); + GRPC_CARES_TRACE_LOG( + "ev_driver=%p on_timeout_locked. driver->shutting_down=%d. err=%s", + driver, driver->shutting_down, grpc_error_string(error)); + if (!driver->shutting_down && error == GRPC_ERROR_NONE) { + grpc_ares_ev_driver_shutdown_locked(driver); + } + grpc_ares_ev_driver_unref(driver); +} + static void on_readable_locked(void* arg, grpc_error* error) { fd_node* fdn = static_cast(arg); grpc_ares_ev_driver* ev_driver = fdn->ev_driver; @@ -314,6 +339,17 @@ void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) { if (!ev_driver->working) { ev_driver->working = true; grpc_ares_notify_on_event_locked(ev_driver); + grpc_millis timeout = + ev_driver->query_timeout_ms == 0 + ? GRPC_MILLIS_INF_FUTURE + : ev_driver->query_timeout_ms + grpc_core::ExecCtx::Get()->Now(); + GRPC_CARES_TRACE_LOG( + "ev_driver=%p grpc_ares_ev_driver_start_locked. timeout in %" PRId64 + " ms", + ev_driver, timeout); + grpc_ares_ev_driver_ref(ev_driver); + grpc_timer_init(&ev_driver->query_timeout, timeout, + &ev_driver->on_timeout_locked); } } diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h index 671c537fe72..b8cefd9470e 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h @@ -43,6 +43,7 @@ ares_channel* grpc_ares_ev_driver_get_channel_locked( created successfully. */ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver, grpc_pollset_set* pollset_set, + int query_timeout_ms, grpc_combiner* combiner, grpc_ares_request* request); diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index 582e2203fc7..55715869b63 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -359,7 +359,7 @@ done: void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( grpc_ares_request* r, const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, - bool check_grpclb, grpc_combiner* combiner) { + bool check_grpclb, int query_timeout_ms, grpc_combiner* combiner) { grpc_error* error = GRPC_ERROR_NONE; grpc_ares_hostbyname_request* hr = nullptr; ares_channel* channel = nullptr; @@ -388,7 +388,7 @@ void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( port = gpr_strdup(default_port); } error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties, - combiner, r); + query_timeout_ms, combiner, r); if (error != GRPC_ERROR_NONE) goto error_cleanup; channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver); // If dns_server is specified, use it. @@ -522,7 +522,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout_ms, grpc_combiner* combiner) { grpc_ares_request* r = static_cast(gpr_zalloc(sizeof(grpc_ares_request))); r->ev_driver = nullptr; @@ -546,7 +546,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( // Look up name using c-ares lib. grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( r, dns_server, name, default_port, interested_parties, check_grpclb, - combiner); + query_timeout_ms, combiner); return r; } @@ -554,6 +554,7 @@ grpc_ares_request* (*grpc_dns_lookup_ares_locked)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, + int query_timeout_ms, grpc_combiner* combiner) = grpc_dns_lookup_ares_locked_impl; static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) { @@ -648,7 +649,8 @@ static void grpc_resolve_address_invoke_dns_lookup_ares_locked( r->ares_request = grpc_dns_lookup_ares_locked( nullptr /* dns_server */, r->name, r->default_port, r->interested_parties, &r->on_dns_lookup_done_locked, &r->lb_addrs, false /* check_grpclb */, - nullptr /* service_config_json */, r->combiner); + nullptr /* service_config_json */, GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS, + r->combiner); } static void grpc_resolve_address_ares_impl(const char* name, diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h index a1231cc4e0d..9acef1d0ca9 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h @@ -26,6 +26,8 @@ #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/resolve_address.h" +#define GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS 10000 + extern grpc_core::TraceFlag grpc_trace_cares_address_sorting; extern grpc_core::TraceFlag grpc_trace_cares_resolver; @@ -60,7 +62,7 @@ extern grpc_ares_request* (*grpc_dns_lookup_ares_locked)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addresses, bool check_grpclb, - char** service_config_json, grpc_combiner* combiner); + char** service_config_json, int query_timeout_ms, grpc_combiner* combiner); /* Cancel the pending grpc_ares_request \a request */ extern void (*grpc_cancel_ares_request_locked)(grpc_ares_request* request); diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc index 9f293c1ac07..fc78b183044 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc @@ -30,7 +30,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout_ms, grpc_combiner* combiner) { return NULL; } @@ -38,6 +38,7 @@ grpc_ares_request* (*grpc_dns_lookup_ares_locked)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, + int query_timeout_ms, grpc_combiner* combiner) = grpc_dns_lookup_ares_locked_impl; static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {} diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index b1b8c0083b1..99c675f503a 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -1390,6 +1390,7 @@ static void perform_stream_op_locked(void* stream_op, GRPC_STATS_INC_HTTP2_OP_BATCHES(); s->context = op->payload->context; + s->traced = op->is_traced; if (grpc_http_trace.enabled()) { char* str = grpc_transport_stream_op_batch_string(op); gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p", str, diff --git a/src/core/ext/transport/chttp2/transport/context_list.cc b/src/core/ext/transport/chttp2/transport/context_list.cc index 4acd0c95833..f30d41c3326 100644 --- a/src/core/ext/transport/chttp2/transport/context_list.cc +++ b/src/core/ext/transport/chttp2/transport/context_list.cc @@ -32,6 +32,7 @@ void ContextList::Execute(void* arg, grpc_core::Timestamps* ts, while (head != nullptr) { if (error == GRPC_ERROR_NONE && ts != nullptr) { if (write_timestamps_callback_g) { + ts->byte_offset = static_cast(head->byte_offset_); write_timestamps_callback_g(head->s_->context, ts); } } diff --git a/src/core/ext/transport/chttp2/transport/context_list.h b/src/core/ext/transport/chttp2/transport/context_list.h index 68d11e94d86..d8701077494 100644 --- a/src/core/ext/transport/chttp2/transport/context_list.h +++ b/src/core/ext/transport/chttp2/transport/context_list.h @@ -50,6 +50,7 @@ class ContextList { /* Create a new element in the list and add it at the front */ ContextList* elem = grpc_core::New(); elem->s_ = s; + elem->byte_offset_ = s->byte_counter; elem->next_ = *head; *head = elem; } @@ -61,6 +62,7 @@ class ContextList { private: grpc_chttp2_stream* s_ = nullptr; ContextList* next_ = nullptr; + size_t byte_offset_ = 0; }; void grpc_http2_set_write_timestamps_callback( diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 1c79cf63531..6aa68f5d4a9 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -642,10 +642,12 @@ struct grpc_chttp2_stream { /** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed */ bool unprocessed_incoming_frames_decompressed = false; - /** gRPC header bytes that are already decompressed */ - size_t decompressed_header_bytes = 0; /** Whether the bytes needs to be traced using Fathom */ bool traced = false; + /** gRPC header bytes that are already decompressed */ + size_t decompressed_header_bytes = 0; + /** Byte counter for number of bytes written */ + size_t byte_counter = 0; }; /** Transport writing call flow: diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc index 77320b496f9..265d3365d3c 100644 --- a/src/core/ext/transport/chttp2/transport/writing.cc +++ b/src/core/ext/transport/chttp2/transport/writing.cc @@ -363,6 +363,7 @@ class DataSendContext { grpc_chttp2_encode_data(s_->id, &s_->compressed_data_buffer, send_bytes, is_last_frame_, &s_->stats.outgoing, &t_->outbuf); s_->flow_control->SentData(send_bytes); + s_->byte_counter += send_bytes; if (s_->compressed_data_buffer.length == 0) { s_->sending_bytes += s_->uncompressed_data_size; } @@ -488,9 +489,6 @@ class StreamWriteContext { return; // early out: nothing to do } - if (s_->traced && grpc_endpoint_can_track_err(t_->ep)) { - grpc_core::ContextList::Append(&t_->cl, s_); - } while ((s_->flow_controlled_buffer.length > 0 || s_->compressed_data_buffer.length > 0) && data_send_context.max_outgoing() > 0) { @@ -500,6 +498,9 @@ class StreamWriteContext { data_send_context.CompressMoreBytes(); } } + if (s_->traced && grpc_endpoint_can_track_err(t_->ep)) { + grpc_core::ContextList::Append(&t_->cl, s_); + } write_context_->ResetPingClock(); if (data_send_context.is_last_frame()) { SentLastFrame(); diff --git a/src/core/lib/gprpp/inlined_vector.h b/src/core/lib/gprpp/inlined_vector.h index 65c2b9634f2..66dc751a567 100644 --- a/src/core/lib/gprpp/inlined_vector.h +++ b/src/core/lib/gprpp/inlined_vector.h @@ -100,10 +100,7 @@ class InlinedVector { void reserve(size_t capacity) { if (capacity > capacity_) { T* new_dynamic = static_cast(gpr_malloc(sizeof(T) * capacity)); - for (size_t i = 0; i < size_; ++i) { - new (&new_dynamic[i]) T(std::move(data()[i])); - data()[i].~T(); - } + move_elements(data(), new_dynamic, size_); gpr_free(dynamic_); dynamic_ = new_dynamic; capacity_ = capacity; @@ -131,13 +128,25 @@ class InlinedVector { size_--; } + size_t size() const { return size_; } + bool empty() const { return size_ == 0; } + + size_t capacity() const { return capacity_; } + + void clear() { + destroy_elements(); + init_data(); + } + + private: void copy_from(const InlinedVector& v) { - // if v is allocated, copy over the buffer. + // if v is allocated, make sure we have enough capacity. if (v.dynamic_ != nullptr) { reserve(v.capacity_); - memcpy(dynamic_, v.dynamic_, v.size_ * sizeof(T)); - } else { - memcpy(inline_, v.inline_, v.size_ * sizeof(T)); + } + // copy over elements + for (size_t i = 0; i < v.size_; ++i) { + new (&(data()[i])) T(v[i]); } // copy over metadata size_ = v.size_; @@ -145,11 +154,12 @@ class InlinedVector { } void move_from(InlinedVector& v) { - // if v is allocated, then we steal its buffer, else we copy it. + // if v is allocated, then we steal its dynamic array; otherwise, we + // move the elements individually. if (v.dynamic_ != nullptr) { dynamic_ = v.dynamic_; } else { - memcpy(inline_, v.inline_, v.size_ * sizeof(T)); + move_elements(v.data(), data(), v.size_); } // copy over metadata size_ = v.size_; @@ -158,17 +168,13 @@ class InlinedVector { v.init_data(); } - size_t size() const { return size_; } - bool empty() const { return size_ == 0; } - - size_t capacity() const { return capacity_; } - - void clear() { - destroy_elements(); - init_data(); + static void move_elements(T* src, T* dst, size_t num_elements) { + for (size_t i = 0; i < num_elements; ++i) { + new (&dst[i]) T(std::move(src[i])); + src[i].~T(); + } } - private: void init_data() { dynamic_ = nullptr; size_ = 0; diff --git a/src/core/lib/iomgr/buffer_list.cc b/src/core/lib/iomgr/buffer_list.cc index e20dab15b18..ace17a108d1 100644 --- a/src/core/lib/iomgr/buffer_list.cc +++ b/src/core/lib/iomgr/buffer_list.cc @@ -35,6 +35,9 @@ void TracedBuffer::AddNewEntry(TracedBuffer** head, uint32_t seq_no, TracedBuffer* new_elem = New(seq_no, arg); /* Store the current time as the sendmsg time. */ new_elem->ts_.sendmsg_time = gpr_now(GPR_CLOCK_REALTIME); + new_elem->ts_.scheduled_time = gpr_inf_past(GPR_CLOCK_REALTIME); + new_elem->ts_.sent_time = gpr_inf_past(GPR_CLOCK_REALTIME); + new_elem->ts_.acked_time = gpr_inf_past(GPR_CLOCK_REALTIME); if (*head == nullptr) { *head = new_elem; return; diff --git a/src/core/lib/iomgr/buffer_list.h b/src/core/lib/iomgr/buffer_list.h index 87d74f9ce27..627f1bde99a 100644 --- a/src/core/lib/iomgr/buffer_list.h +++ b/src/core/lib/iomgr/buffer_list.h @@ -37,6 +37,8 @@ struct Timestamps { gpr_timespec scheduled_time; gpr_timespec sent_time; gpr_timespec acked_time; + + uint32_t byte_offset; /* byte offset relative to the start of the RPC */ }; /** TracedBuffer is a class to keep track of timestamps for a specific buffer in @@ -73,7 +75,7 @@ class TracedBuffer { private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - TracedBuffer(int seq_no, void* arg) + TracedBuffer(uint32_t seq_no, void* arg) : seq_no_(seq_no), arg_(arg), next_(nullptr) {} uint32_t seq_no_; /* The sequence number for the last byte in the buffer */ diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc index 38571b1957b..4b8c891e9b0 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.cc +++ b/src/core/lib/iomgr/ev_epoll1_linux.cc @@ -1242,6 +1242,8 @@ static void pollset_set_del_pollset_set(grpc_pollset_set* bag, * Event engine binding */ +static void shutdown_background_closure(void) {} + static void shutdown_engine(void) { fd_global_shutdown(); pollset_global_shutdown(); @@ -1255,6 +1257,7 @@ static void shutdown_engine(void) { static const grpc_event_engine_vtable vtable = { sizeof(grpc_pollset), true, + false, fd_create, fd_wrapped_fd, @@ -1284,6 +1287,7 @@ static const grpc_event_engine_vtable vtable = { pollset_set_add_fd, pollset_set_del_fd, + shutdown_background_closure, shutdown_engine, }; diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index 06a382c5560..7a4870db785 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -1604,6 +1604,8 @@ static void pollset_set_del_pollset_set(grpc_pollset_set* bag, * Event engine binding */ +static void shutdown_background_closure(void) {} + static void shutdown_engine(void) { fd_global_shutdown(); pollset_global_shutdown(); @@ -1612,6 +1614,7 @@ static void shutdown_engine(void) { static const grpc_event_engine_vtable vtable = { sizeof(grpc_pollset), true, + false, fd_create, fd_wrapped_fd, @@ -1641,6 +1644,7 @@ static const grpc_event_engine_vtable vtable = { pollset_set_add_fd, pollset_set_del_fd, + shutdown_background_closure, shutdown_engine, }; diff --git a/src/core/lib/iomgr/ev_poll_posix.cc b/src/core/lib/iomgr/ev_poll_posix.cc index 16562538a63..67cbfbbd021 100644 --- a/src/core/lib/iomgr/ev_poll_posix.cc +++ b/src/core/lib/iomgr/ev_poll_posix.cc @@ -1782,6 +1782,8 @@ static void global_cv_fd_table_shutdown() { * event engine binding */ +static void shutdown_background_closure(void) {} + static void shutdown_engine(void) { pollset_global_shutdown(); if (grpc_cv_wakeup_fds_enabled()) { @@ -1796,6 +1798,7 @@ static void shutdown_engine(void) { static const grpc_event_engine_vtable vtable = { sizeof(grpc_pollset), false, + false, fd_create, fd_wrapped_fd, @@ -1825,6 +1828,7 @@ static const grpc_event_engine_vtable vtable = { pollset_set_add_fd, pollset_set_del_fd, + shutdown_background_closure, shutdown_engine, }; diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc index 6f6d134cedb..32d1b6c43ef 100644 --- a/src/core/lib/iomgr/ev_posix.cc +++ b/src/core/lib/iomgr/ev_posix.cc @@ -244,6 +244,10 @@ bool grpc_event_engine_can_track_errors(void) { return false; } +bool grpc_event_engine_run_in_background(void) { + return g_event_engine->run_in_background; +} + grpc_fd* grpc_fd_create(int fd, const char* name, bool track_err) { GRPC_POLLING_API_TRACE("fd_create(%d, %s, %d)", fd, name, track_err); GRPC_FD_TRACE("fd_create(%d, %s, %d)", fd, name, track_err); @@ -395,4 +399,8 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) { g_event_engine->pollset_set_del_fd(pollset_set, fd); } +void grpc_shutdown_background_closure(void) { + g_event_engine->shutdown_background_closure(); +} + #endif // GRPC_POSIX_SOCKET_EV diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h index b8fb8f534b4..812c7a0f0f8 100644 --- a/src/core/lib/iomgr/ev_posix.h +++ b/src/core/lib/iomgr/ev_posix.h @@ -42,6 +42,7 @@ typedef struct grpc_fd grpc_fd; typedef struct grpc_event_engine_vtable { size_t pollset_size; bool can_track_err; + bool run_in_background; grpc_fd* (*fd_create)(int fd, const char* name, bool track_err); int (*fd_wrapped_fd)(grpc_fd* fd); @@ -79,6 +80,7 @@ typedef struct grpc_event_engine_vtable { void (*pollset_set_add_fd)(grpc_pollset_set* pollset_set, grpc_fd* fd); void (*pollset_set_del_fd)(grpc_pollset_set* pollset_set, grpc_fd* fd); + void (*shutdown_background_closure)(void); void (*shutdown_engine)(void); } grpc_event_engine_vtable; @@ -101,6 +103,11 @@ const char* grpc_get_poll_strategy_name(); */ bool grpc_event_engine_can_track_errors(); +/* Returns true if polling engine runs in the background, false otherwise. + * Currently only 'epollbg' runs in the background. + */ +bool grpc_event_engine_run_in_background(); + /* Create a wrapped file descriptor. Requires fd is a non-blocking file descriptor. \a track_err if true means that error events would be tracked separately @@ -174,6 +181,9 @@ void grpc_pollset_add_fd(grpc_pollset* pollset, struct grpc_fd* fd); void grpc_pollset_set_add_fd(grpc_pollset_set* pollset_set, grpc_fd* fd); void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd); +/* Shut down all the closures registered in the background poller. */ +void grpc_shutdown_background_closure(); + /* override to allow tests to hook poll() usage */ typedef int (*grpc_poll_function_type)(struct pollfd*, nfds_t, int); extern grpc_poll_function_type grpc_poll_function; diff --git a/src/core/lib/iomgr/fork_posix.cc b/src/core/lib/iomgr/fork_posix.cc index e957bad73d3..05ecd2a49b7 100644 --- a/src/core/lib/iomgr/fork_posix.cc +++ b/src/core/lib/iomgr/fork_posix.cc @@ -60,7 +60,7 @@ void grpc_prefork() { } if (strcmp(grpc_get_poll_strategy_name(), "epoll1") != 0 && strcmp(grpc_get_poll_strategy_name(), "poll") != 0) { - gpr_log(GPR_ERROR, + gpr_log(GPR_INFO, "Fork support is only compatible with the epoll1 and poll polling " "strategies"); } diff --git a/src/core/lib/iomgr/iomgr.cc b/src/core/lib/iomgr/iomgr.cc index fd09a6863b8..eb29973514f 100644 --- a/src/core/lib/iomgr/iomgr.cc +++ b/src/core/lib/iomgr/iomgr.cc @@ -157,6 +157,10 @@ void grpc_iomgr_shutdown() { gpr_cv_destroy(&g_rcv); } +void grpc_iomgr_shutdown_background_closure() { + grpc_iomgr_platform_shutdown_background_closure(); +} + void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name) { obj->name = gpr_strdup(name); gpr_mu_lock(&g_mu); diff --git a/src/core/lib/iomgr/iomgr.h b/src/core/lib/iomgr/iomgr.h index 537ef8a6ffe..8ea9289e068 100644 --- a/src/core/lib/iomgr/iomgr.h +++ b/src/core/lib/iomgr/iomgr.h @@ -35,6 +35,10 @@ void grpc_iomgr_start(); * exec_ctx. */ void grpc_iomgr_shutdown(); +/** Signals the intention to shutdown all the closures registered in the + * background poller. */ +void grpc_iomgr_shutdown_background_closure(); + /* Exposed only for testing */ size_t grpc_iomgr_count_objects_for_testing(); diff --git a/src/core/lib/iomgr/iomgr_custom.cc b/src/core/lib/iomgr/iomgr_custom.cc index d34c8e7cd14..4b112c9097f 100644 --- a/src/core/lib/iomgr/iomgr_custom.cc +++ b/src/core/lib/iomgr/iomgr_custom.cc @@ -40,9 +40,11 @@ static void iomgr_platform_init(void) { } static void iomgr_platform_flush(void) {} static void iomgr_platform_shutdown(void) { grpc_pollset_global_shutdown(); } +static void iomgr_platform_shutdown_background_closure(void) {} static grpc_iomgr_platform_vtable vtable = { - iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown}; + iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, + iomgr_platform_shutdown_background_closure}; void grpc_custom_iomgr_init(grpc_socket_vtable* socket, grpc_custom_resolver_vtable* resolver, diff --git a/src/core/lib/iomgr/iomgr_internal.cc b/src/core/lib/iomgr/iomgr_internal.cc index 32dbabb79dc..b6c9211865d 100644 --- a/src/core/lib/iomgr/iomgr_internal.cc +++ b/src/core/lib/iomgr/iomgr_internal.cc @@ -41,3 +41,7 @@ void grpc_iomgr_platform_init() { iomgr_platform_vtable->init(); } void grpc_iomgr_platform_flush() { iomgr_platform_vtable->flush(); } void grpc_iomgr_platform_shutdown() { iomgr_platform_vtable->shutdown(); } + +void grpc_iomgr_platform_shutdown_background_closure() { + iomgr_platform_vtable->shutdown_background_closure(); +} diff --git a/src/core/lib/iomgr/iomgr_internal.h b/src/core/lib/iomgr/iomgr_internal.h index b011d9c7b19..bca7409907f 100644 --- a/src/core/lib/iomgr/iomgr_internal.h +++ b/src/core/lib/iomgr/iomgr_internal.h @@ -35,6 +35,7 @@ typedef struct grpc_iomgr_platform_vtable { void (*init)(void); void (*flush)(void); void (*shutdown)(void); + void (*shutdown_background_closure)(void); } grpc_iomgr_platform_vtable; void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name); @@ -52,6 +53,9 @@ void grpc_iomgr_platform_flush(void); /** tear down all platform specific global iomgr structures */ void grpc_iomgr_platform_shutdown(void); +/** shut down all the closures registered in the background poller */ +void grpc_iomgr_platform_shutdown_background_closure(void); + bool grpc_iomgr_abort_on_leaks(void); #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H */ diff --git a/src/core/lib/iomgr/iomgr_posix.cc b/src/core/lib/iomgr/iomgr_posix.cc index ca7334c9a4b..9386adf060d 100644 --- a/src/core/lib/iomgr/iomgr_posix.cc +++ b/src/core/lib/iomgr/iomgr_posix.cc @@ -51,8 +51,13 @@ static void iomgr_platform_shutdown(void) { grpc_wakeup_fd_global_destroy(); } +static void iomgr_platform_shutdown_background_closure(void) { + grpc_shutdown_background_closure(); +} + static grpc_iomgr_platform_vtable vtable = { - iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown}; + iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, + iomgr_platform_shutdown_background_closure}; void grpc_set_default_iomgr_platform() { grpc_set_tcp_client_impl(&grpc_posix_tcp_client_vtable); diff --git a/src/core/lib/iomgr/iomgr_posix_cfstream.cc b/src/core/lib/iomgr/iomgr_posix_cfstream.cc index 235a9e0712f..552ef4309c8 100644 --- a/src/core/lib/iomgr/iomgr_posix_cfstream.cc +++ b/src/core/lib/iomgr/iomgr_posix_cfstream.cc @@ -54,8 +54,13 @@ static void iomgr_platform_shutdown(void) { grpc_wakeup_fd_global_destroy(); } +static void iomgr_platform_shutdown_background_closure(void) { + grpc_shutdown_background_closure(); +} + static grpc_iomgr_platform_vtable vtable = { - iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown}; + iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, + iomgr_platform_shutdown_background_closure}; void grpc_set_default_iomgr_platform() { char* enable_cfstream = getenv(grpc_cfstream_env_var); diff --git a/src/core/lib/iomgr/iomgr_windows.cc b/src/core/lib/iomgr/iomgr_windows.cc index cdef89cbf04..24ef0dba7b4 100644 --- a/src/core/lib/iomgr/iomgr_windows.cc +++ b/src/core/lib/iomgr/iomgr_windows.cc @@ -71,8 +71,11 @@ static void iomgr_platform_shutdown(void) { winsock_shutdown(); } +static void iomgr_platform_shutdown_background_closure(void) {} + static grpc_iomgr_platform_vtable vtable = { - iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown}; + iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, + iomgr_platform_shutdown_background_closure}; void grpc_set_default_iomgr_platform() { grpc_set_tcp_client_impl(&grpc_windows_tcp_client_vtable); diff --git a/src/core/lib/iomgr/resolve_address.h b/src/core/lib/iomgr/resolve_address.h index 6afe94a7a92..7016ffc31aa 100644 --- a/src/core/lib/iomgr/resolve_address.h +++ b/src/core/lib/iomgr/resolve_address.h @@ -65,7 +65,7 @@ void grpc_set_resolver_impl(grpc_address_resolver_vtable* vtable); /* Asynchronously resolve addr. Use default_port if a port isn't designated in addr, otherwise use the port in addr. */ -/* TODO(ctiller): add a timeout here */ +/* TODO(apolcyn): add a timeout here */ void grpc_resolve_address(const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 4a5ca615e5a..cfcb190d601 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -260,10 +260,17 @@ static void notify_on_write(grpc_tcp* tcp) { if (grpc_tcp_trace.enabled()) { gpr_log(GPR_INFO, "TCP:%p notify_on_write", tcp); } - cover_self(tcp); - GRPC_CLOSURE_INIT(&tcp->write_done_closure, - tcp_drop_uncovered_then_handle_write, tcp, - grpc_schedule_on_exec_ctx); + if (grpc_event_engine_run_in_background()) { + // If there is a polling engine always running in the background, there is + // no need to run the backup poller. + GRPC_CLOSURE_INIT(&tcp->write_done_closure, tcp_handle_write, tcp, + grpc_schedule_on_exec_ctx); + } else { + cover_self(tcp); + GRPC_CLOSURE_INIT(&tcp->write_done_closure, + tcp_drop_uncovered_then_handle_write, tcp, + grpc_schedule_on_exec_ctx); + } grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_done_closure); } @@ -627,7 +634,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, if (sending_length == static_cast(length)) { gpr_mu_lock(&tcp->tb_mu); grpc_core::TracedBuffer::AddNewEntry( - &tcp->tb_head, static_cast(tcp->bytes_counter + length), + &tcp->tb_head, static_cast(tcp->bytes_counter + length), tcp->outgoing_buffer_arg); gpr_mu_unlock(&tcp->tb_mu); tcp->outgoing_buffer_arg = nullptr; @@ -679,11 +686,9 @@ struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg, } /** For linux platforms, reads the socket's error queue and processes error - * messages from the queue. Returns true if all the errors processed were - * timestamps. Returns false if any of the errors were not timestamps. For - * non-linux platforms, error processing is not used/enabled currently. + * messages from the queue. */ -static bool process_errors(grpc_tcp* tcp) { +static void process_errors(grpc_tcp* tcp) { while (true) { struct iovec iov; iov.iov_base = nullptr; @@ -712,10 +717,10 @@ static bool process_errors(grpc_tcp* tcp) { } while (r < 0 && saved_errno == EINTR); if (r == -1 && saved_errno == EAGAIN) { - return true; /* No more errors to process */ + return; /* No more errors to process */ } if (r == -1) { - return false; + return; } if (grpc_tcp_trace.enabled()) { if ((msg.msg_flags & MSG_CTRUNC) == 1) { @@ -725,8 +730,9 @@ static bool process_errors(grpc_tcp* tcp) { if (msg.msg_controllen == 0) { /* There was no control message found. It was probably spurious. */ - return true; + return; } + bool seen = false; for (auto cmsg = CMSG_FIRSTHDR(&msg); cmsg && cmsg->cmsg_len; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level != SOL_SOCKET || @@ -738,9 +744,13 @@ static bool process_errors(grpc_tcp* tcp) { "unknown control message cmsg_level:%d cmsg_type:%d", cmsg->cmsg_level, cmsg->cmsg_type); } - return false; + return; } cmsg = process_timestamp(tcp, &msg, cmsg); + seen = true; + } + if (!seen) { + return; } } } diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index c6198b8ae76..67cf5d89bff 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -161,6 +161,7 @@ void grpc_shutdown(void) { if (--g_initializations == 0) { { grpc_core::ExecCtx exec_ctx(0); + grpc_iomgr_shutdown_background_closure(); { grpc_timer_manager_set_threading( false); // shutdown timer_manager thread diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index cbdb77c8441..b32f9c6ec1a 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -27,6 +27,7 @@ #include #include +#include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/slice/slice_internal.h" @@ -149,7 +150,7 @@ void grpc_transport_move_stats(grpc_transport_stream_stats* from, } size_t grpc_transport_stream_size(grpc_transport* transport) { - return transport->vtable->sizeof_stream; + return GPR_ROUND_UP_TO_ALIGNMENT_SIZE(transport->vtable->sizeof_stream); } void grpc_transport_destroy(grpc_transport* transport) { diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index edfa7030d13..5ce568834e9 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -129,7 +129,8 @@ struct grpc_transport_stream_op_batch { recv_initial_metadata(false), recv_message(false), recv_trailing_metadata(false), - cancel_stream(false) {} + cancel_stream(false), + is_traced(false) {} /** Should be scheduled when all of the non-recv operations in the batch are complete. @@ -167,6 +168,9 @@ struct grpc_transport_stream_op_batch { /** Cancel this stream with the provided error */ bool cancel_stream : 1; + /** Is this stream traced */ + bool is_traced : 1; + /*************************************************************************** * remaining fields are initialized and used at the discretion of the * current handler of the op */ diff --git a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc index 1de6264183a..43d0979f4b9 100644 --- a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +++ b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc @@ -116,12 +116,13 @@ void alts_handshaker_client_handle_response(alts_handshaker_client* c, "cb is nullptr in alts_tsi_handshaker_handle_response()"); return; } - if (handshaker == nullptr || recv_buffer == nullptr) { + if (handshaker == nullptr) { gpr_log(GPR_ERROR, - "Invalid arguments to alts_tsi_handshaker_handle_response()"); + "handshaker is nullptr in alts_tsi_handshaker_handle_response()"); cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr); return; } + /* TSI handshake has been shutdown. */ if (alts_tsi_handshaker_has_shutdown(handshaker)) { gpr_log(GPR_ERROR, "TSI handshake shutdown"); cb(TSI_HANDSHAKE_SHUTDOWN, user_data, nullptr, 0, nullptr); @@ -133,6 +134,12 @@ void alts_handshaker_client_handle_response(alts_handshaker_client* c, cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr); return; } + if (recv_buffer == nullptr) { + gpr_log(GPR_ERROR, + "recv_buffer is nullptr in alts_tsi_handshaker_handle_response()"); + cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr); + return; + } grpc_gcp_handshaker_resp* resp = alts_tsi_utils_deserialize_response(recv_buffer); grpc_byte_buffer_destroy(client->recv_buffer); diff --git a/src/cpp/client/generic_stub.cc b/src/cpp/client/generic_stub.cc index 87902b26f0e..f61c1b5317b 100644 --- a/src/cpp/client/generic_stub.cc +++ b/src/cpp/client/generic_stub.cc @@ -72,4 +72,13 @@ void GenericStub::experimental_type::UnaryCall( context, request, response, std::move(on_completion)); } +void GenericStub::experimental_type::PrepareBidiStreamingCall( + ClientContext* context, const grpc::string& method, + experimental::ClientBidiReactor* reactor) { + internal::ClientCallbackReaderWriterFactory::Create( + stub_->channel_.get(), + internal::RpcMethod(method.c_str(), internal::RpcMethod::BIDI_STREAMING), + context, reactor); +} + } // namespace grpc diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 0a51cf5626e..69af43a6562 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -291,7 +291,7 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { void ContinueRunAfterInterception() { { - ctx_.BeginCompletionOp(&call_, false); + ctx_.BeginCompletionOp(&call_, nullptr, nullptr); global_callbacks_->PreSynchronousRequest(&ctx_); auto* handler = resources_ ? method_->handler() : server_->resource_exhausted_handler_.get(); @@ -456,7 +456,6 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { } } void ContinueRunAfterInterception() { - req_->ctx_.BeginCompletionOp(call_, true); req_->method_->handler()->RunHandler( internal::MethodHandler::HandlerParameter( call_, &req_->ctx_, req_->request_, req_->request_status_, @@ -1018,7 +1017,7 @@ bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag, } } if (*status && call_) { - context_->BeginCompletionOp(&call_wrapper_, false); + context_->BeginCompletionOp(&call_wrapper_, nullptr, nullptr); } *tag = tag_; if (delete_on_finalize_) { @@ -1029,7 +1028,7 @@ bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag, void ServerInterface::BaseAsyncRequest:: ContinueFinalizeResultAfterInterception() { - context_->BeginCompletionOp(&call_wrapper_, false); + context_->BeginCompletionOp(&call_wrapper_, nullptr, nullptr); // Queue a tag which will be returned immediately grpc_core::ExecCtx exec_ctx; grpc_cq_begin_op(notification_cq_->cq(), this); diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 9c01f896e6c..1b524bc3e83 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -41,8 +42,9 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { public: // initial refs: one in the server context, one in the cq // must ref the call before calling constructor and after deleting this - CompletionOp(internal::Call* call) + CompletionOp(internal::Call* call, internal::ServerReactor* reactor) : call_(*call), + reactor_(reactor), has_tag_(false), tag_(nullptr), core_cq_tag_(this), @@ -124,9 +126,9 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { return; } /* Start a dummy op so that we can return the tag */ - GPR_CODEGEN_ASSERT(GRPC_CALL_OK == - g_core_codegen_interface->grpc_call_start_batch( - call_.call(), nullptr, 0, this, nullptr)); + GPR_CODEGEN_ASSERT( + GRPC_CALL_OK == + grpc_call_start_batch(call_.call(), nullptr, 0, core_cq_tag_, nullptr)); } private: @@ -136,13 +138,14 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { } internal::Call call_; + internal::ServerReactor* reactor_; bool has_tag_; void* tag_; void* core_cq_tag_; std::mutex mu_; int refs_; bool finalized_; - int cancelled_; + int cancelled_; // This is an int (not bool) because it is passed to core bool done_intercepting_; internal::InterceptorBatchMethodsImpl interceptor_methods_; }; @@ -190,7 +193,16 @@ bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { } finalized_ = true; - if (!*status) cancelled_ = 1; + // If for some reason the incoming status is false, mark that as a + // cancellation. + // TODO(vjpai): does this ever happen? + if (!*status) { + cancelled_ = 1; + } + + if (cancelled_ && (reactor_ != nullptr)) { + reactor_->OnCancel(); + } /* Release the lock since we are going to be running through interceptors now */ lock.unlock(); @@ -251,21 +263,25 @@ void ServerContext::Clear() { initial_metadata_.clear(); trailing_metadata_.clear(); client_metadata_.Reset(); - if (call_) { - grpc_call_unref(call_); - } if (completion_op_) { completion_op_->Unref(); + completion_op_ = nullptr; completion_tag_.Clear(); } if (rpc_info_) { rpc_info_->Unref(); + rpc_info_ = nullptr; + } + if (call_) { + auto* call = call_; + call_ = nullptr; + grpc_call_unref(call); } - // Don't need to clear out call_, completion_op_, or rpc_info_ because this is - // either called from destructor or just before Setup } -void ServerContext::BeginCompletionOp(internal::Call* call, bool callback) { +void ServerContext::BeginCompletionOp(internal::Call* call, + std::function callback, + internal::ServerReactor* reactor) { GPR_ASSERT(!completion_op_); if (rpc_info_) { rpc_info_->Ref(); @@ -273,10 +289,11 @@ void ServerContext::BeginCompletionOp(internal::Call* call, bool callback) { grpc_call_ref(call->call()); completion_op_ = new (grpc_call_arena_alloc(call->call(), sizeof(CompletionOp))) - CompletionOp(call); - if (callback) { - completion_tag_.Set(call->call(), nullptr, completion_op_); + CompletionOp(call, reactor); + if (callback != nullptr) { + completion_tag_.Set(call->call(), std::move(callback), completion_op_); completion_op_->set_core_cq_tag(&completion_tag_); + completion_op_->set_tag(completion_op_); } else if (has_notify_when_done_tag_) { completion_op_->set_tag(async_notify_when_done_tag_); } diff --git a/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs b/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs index 3a161763fd0..b10d7a10451 100644 --- a/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs +++ b/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs @@ -25,7 +25,7 @@ namespace Grpc.Core.Tests { public class AppDomainUnloadTest { -#if NETCOREAPP1_0 +#if NETCOREAPP1_1 || NETCOREAPP2_1 [Test] [Ignore("Not supported for CoreCLR")] public void AppDomainUnloadHookCanCleanupAbandonedCall() diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj index d58f0468244..178931a3d72 100755 --- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj +++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.Core.Tests Exe Grpc.Core.Tests diff --git a/src/csharp/Grpc.Core.Tests/NUnitMain.cs b/src/csharp/Grpc.Core.Tests/NUnitMain.cs index 49cb8cd3b99..221a6b823a4 100644 --- a/src/csharp/Grpc.Core.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.Core.Tests/NUnitMain.cs @@ -34,7 +34,7 @@ namespace Grpc.Core.Tests { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new ConsoleLogger()); -#if NETCOREAPP1_0 +#if NETCOREAPP1_1 || NETCOREAPP2_1 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); diff --git a/src/csharp/Grpc.Core.Tests/SanityTest.cs b/src/csharp/Grpc.Core.Tests/SanityTest.cs index 0904453b6e9..f785f70f4ce 100644 --- a/src/csharp/Grpc.Core.Tests/SanityTest.cs +++ b/src/csharp/Grpc.Core.Tests/SanityTest.cs @@ -31,7 +31,7 @@ namespace Grpc.Core.Tests public class SanityTest { // TODO: make sanity test work for CoreCLR as well -#if !NETCOREAPP1_0 +#if !NETCOREAPP1_1 && !NETCOREAPP2_1 /// /// Because we depend on a native library, sometimes when things go wrong, the /// entire NUnit test process crashes. To be able to track down problems better, @@ -44,7 +44,7 @@ namespace Grpc.Core.Tests public void TestsJsonUpToDate() { var discoveredTests = DiscoverAllTestClasses(); - var testsFromFile + var testsFromFile = JsonConvert.DeserializeObject>>(ReadTestsJson()); Assert.AreEqual(discoveredTests, testsFromFile); diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs index f526b913af0..5177b69fd90 100644 --- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs +++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs @@ -83,13 +83,13 @@ namespace Grpc.Core.Internal // See https://github.com/grpc/grpc/pull/7303 for one option. var assemblyDirectory = Path.GetDirectoryName(GetAssemblyPath()); - // With old-style VS projects, the native libraries get copied using a .targets rule to the build output folder + // With "classic" VS projects, the native libraries get copied using a .targets rule to the build output folder // alongside the compiled assembly. // With dotnet cli projects targeting net45 framework, the native libraries (just the required ones) // are similarly copied to the built output folder, through the magic of Microsoft.NETCore.Platforms. var classicPath = Path.Combine(assemblyDirectory, GetNativeLibraryFilename()); - // With dotnet cli project targeting netcoreapp1.0, projects will use Grpc.Core assembly directly in the location where it got restored + // With dotnet cli project targeting netcoreappX.Y, projects will use Grpc.Core assembly directly in the location where it got restored // by nuget. We locate the native libraries based on known structure of Grpc.Core nuget package. // When "dotnet publish" is used, the runtimes directory is copied next to the published assemblies. string runtimesDirectory = string.Format("runtimes/{0}/native", GetPlatformString()); diff --git a/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj b/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj index db4e3ef4e3f..1afcd9fba0c 100755 --- a/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj +++ b/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.Examples.MathClient Exe Grpc.Examples.MathClient diff --git a/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj b/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj index b12b418d015..75ef6d1008b 100755 --- a/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj +++ b/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.Examples.MathServer Exe Grpc.Examples.MathServer diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj index 7493eb8051d..93d112a0c53 100755 --- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj +++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.Examples.Tests Exe Grpc.Examples.Tests diff --git a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs index bcb8b46b644..0b9a5258ef4 100644 --- a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs @@ -34,7 +34,7 @@ namespace Grpc.Examples.Tests { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new ConsoleLogger()); -#if NETCOREAPP1_0 +#if NETCOREAPP1_1 || NETCOREAPP2_1 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); diff --git a/src/csharp/Grpc.Examples/Grpc.Examples.csproj b/src/csharp/Grpc.Examples/Grpc.Examples.csproj index baa3b4ce6c1..9ce2b59d036 100755 --- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj +++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.Examples Grpc.Examples true diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj index 616e56df105..2a037a72e51 100755 --- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj +++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.HealthCheck.Tests Exe Grpc.HealthCheck.Tests diff --git a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs index 365551e8956..f5091863b84 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs @@ -34,7 +34,7 @@ namespace Grpc.HealthCheck.Tests { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new ConsoleLogger()); -#if NETCOREAPP1_0 +#if NETCOREAPP1_1 || NETCOREAPP2_1 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj index 35713156ea2..1cd4b83e1ed 100755 --- a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj +++ b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.IntegrationTesting.Client Exe Grpc.IntegrationTesting.Client diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj index 3ecefe3bc4f..2890a7df588 100755 --- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj +++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.IntegrationTesting.QpsWorker Exe Grpc.IntegrationTesting.QpsWorker diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj index 1092b2c21ef..ee718958bcf 100755 --- a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj +++ b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.IntegrationTesting.Server Exe Grpc.IntegrationTesting.Server @@ -19,7 +19,7 @@ - + diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj b/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj index 22272547f61..99926497e4e 100755 --- a/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj +++ b/src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.IntegrationTesting.StressClient Exe Grpc.IntegrationTesting.StressClient diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 8daf3fa98bb..c342f8a107c 100755 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.IntegrationTesting Exe Grpc.IntegrationTesting diff --git a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs index 9d24762e0ae..6265953622c 100644 --- a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs +++ b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs @@ -34,7 +34,7 @@ namespace Grpc.IntegrationTesting { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new ConsoleLogger()); -#if NETCOREAPP1_0 +#if NETCOREAPP1_1 || NETCOREAPP2_1 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); diff --git a/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj b/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj index d39d46cf1b0..5b1656080ae 100644 --- a/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj +++ b/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.Microbenchmarks Exe Grpc.Microbenchmarks diff --git a/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj index 0c12f38f25a..8b586c6ecb7 100755 --- a/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj +++ b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj @@ -4,7 +4,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Grpc.Reflection.Tests Exe Grpc.Reflection.Tests diff --git a/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs b/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs index 49ed1cc8d44..1be7f6542b3 100644 --- a/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs @@ -34,7 +34,7 @@ namespace Grpc.Reflection.Tests { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new ConsoleLogger()); -#if NETCOREAPP1_0 +#if NETCOREAPP1_1 || NETCOREAPP2_1 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); diff --git a/src/csharp/Grpc.Tools.Tests/Grpc.Tools.Tests.csproj b/src/csharp/Grpc.Tools.Tests/Grpc.Tools.Tests.csproj index a2d4874eece..cfb40f44ae1 100644 --- a/src/csharp/Grpc.Tools.Tests/Grpc.Tools.Tests.csproj +++ b/src/csharp/Grpc.Tools.Tests/Grpc.Tools.Tests.csproj @@ -3,7 +3,7 @@ - net45;netcoreapp1.0 + net45;netcoreapp1.1 Exe diff --git a/src/csharp/Grpc.Tools.Tests/NUnitMain.cs b/src/csharp/Grpc.Tools.Tests/NUnitMain.cs index 418c33820eb..13ba8b51d09 100644 --- a/src/csharp/Grpc.Tools.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.Tools.Tests/NUnitMain.cs @@ -24,7 +24,7 @@ namespace Grpc.Tools.Tests static class NUnitMain { public static int Main(string[] args) => -#if NETCOREAPP1_0 || NETCOREAPP1_1 +#if NETCOREAPP1_1 || NETCOREAPP2_1 new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args); #else new AutoRun().Execute(args); diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c index f7d5a85876b..111c6f4867d 100644 --- a/src/php/ext/grpc/php_grpc.c +++ b/src/php/ext/grpc/php_grpc.c @@ -170,7 +170,9 @@ void prefork() { acquire_persistent_locks(); } -void postfork_child(TSRMLS_D) { +void postfork_child() { + TSRMLS_FETCH(); + // loop through persistant list and destroy all underlying grpc_channel objs destroy_grpc_channels(); diff --git a/src/proto/grpc/channelz/BUILD b/src/proto/grpc/channelz/BUILD index bdb03d5e2d0..b6b485e3e8d 100644 --- a/src/proto/grpc/channelz/BUILD +++ b/src/proto/grpc/channelz/BUILD @@ -24,3 +24,10 @@ grpc_proto_library( has_services = True, well_known_protos = True, ) + +filegroup( + name = "channelz_proto_file", + srcs = [ + "channelz.proto", + ], +) diff --git a/src/proto/grpc/health/v1/BUILD b/src/proto/grpc/health/v1/BUILD index 97642985c9d..38a7d992e06 100644 --- a/src/proto/grpc/health/v1/BUILD +++ b/src/proto/grpc/health/v1/BUILD @@ -29,4 +29,3 @@ filegroup( "health.proto", ], ) - diff --git a/src/proto/grpc/testing/compiler_test.proto b/src/proto/grpc/testing/compiler_test.proto index db5ca483312..9fa5590a594 100644 --- a/src/proto/grpc/testing/compiler_test.proto +++ b/src/proto/grpc/testing/compiler_test.proto @@ -20,6 +20,9 @@ syntax = "proto3"; // Ignored detached comment +// The comments in this file are not meant for readability +// but rather to test to make sure that the code generator +// properly preserves comments on files, services, and RPCs // Ignored package leading comment package grpc.testing; diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index 88c5b6d5be5..6022fc3ef21 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -1723,7 +1723,7 @@ def server(thread_pool, handlers. The interceptors are given control in the order they are specified. This is an EXPERIMENTAL API. options: An optional list of key-value pairs (channel args in gRPC runtime) - to configure the channel. + to configure the channel. maximum_concurrent_rpcs: The maximum number of concurrent RPCs this server will service before returning RESOURCE_EXHAUSTED status, or None to indicate no limit. diff --git a/src/python/grpcio/grpc/_cython/BUILD.bazel b/src/python/grpcio/grpc/_cython/BUILD.bazel index cfd3a51d9bb..e318298d0ab 100644 --- a/src/python/grpcio/grpc/_cython/BUILD.bazel +++ b/src/python/grpcio/grpc/_cython/BUILD.bazel @@ -12,6 +12,7 @@ pyx_library( "_cygrpc/grpc_string.pyx.pxi", "_cygrpc/arguments.pyx.pxi", "_cygrpc/call.pyx.pxi", + "_cygrpc/channelz.pyx.pxi", "_cygrpc/channel.pyx.pxi", "_cygrpc/credentials.pyx.pxi", "_cygrpc/completion_queue.pyx.pxi", diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi new file mode 100644 index 00000000000..113f7976dd9 --- /dev/null +++ b/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi @@ -0,0 +1,69 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def channelz_get_top_channels(start_channel_id): + cdef char *c_returned_str = grpc_channelz_get_top_channels( + start_channel_id, + ) + if c_returned_str == NULL: + raise ValueError('Failed to get top channels, please ensure your' \ + ' start_channel_id==%s is valid' % start_channel_id) + return c_returned_str + +def channelz_get_servers(start_server_id): + cdef char *c_returned_str = grpc_channelz_get_servers(start_server_id) + if c_returned_str == NULL: + raise ValueError('Failed to get servers, please ensure your' \ + ' start_server_id==%s is valid' % start_server_id) + return c_returned_str + +def channelz_get_server(server_id): + cdef char *c_returned_str = grpc_channelz_get_server(server_id) + if c_returned_str == NULL: + raise ValueError('Failed to get the server, please ensure your' \ + ' server_id==%s is valid' % server_id) + return c_returned_str + +def channelz_get_server_sockets(server_id, start_socket_id): + cdef char *c_returned_str = grpc_channelz_get_server_sockets( + server_id, + start_socket_id, + ) + if c_returned_str == NULL: + raise ValueError('Failed to get server sockets, please ensure your' \ + ' server_id==%s and start_socket_id==%s is valid' % + (server_id, start_socket_id)) + return c_returned_str + +def channelz_get_channel(channel_id): + cdef char *c_returned_str = grpc_channelz_get_channel(channel_id) + if c_returned_str == NULL: + raise ValueError('Failed to get the channel, please ensure your' \ + ' channel_id==%s is valid' % (channel_id)) + return c_returned_str + +def channelz_get_subchannel(subchannel_id): + cdef char *c_returned_str = grpc_channelz_get_subchannel(subchannel_id) + if c_returned_str == NULL: + raise ValueError('Failed to get the subchannel, please ensure your' \ + ' subchannel_id==%s is valid' % (subchannel_id)) + return c_returned_str + +def channelz_get_socket(socket_id): + cdef char *c_returned_str = grpc_channelz_get_socket(socket_id) + if c_returned_str == NULL: + raise ValueError('Failed to get the socket, please ensure your' \ + ' socket_id==%s is valid' % (socket_id)) + return c_returned_str diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 5aaf31e36c2..5bbc10af25d 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -13,6 +13,7 @@ # limitations under the License. cimport libc.time +from libc.stdint cimport intptr_t # Typedef types with approximately the same semantics to provide their names to @@ -384,6 +385,15 @@ cdef extern from "grpc/grpc.h": void grpc_server_cancel_all_calls(grpc_server *server) nogil void grpc_server_destroy(grpc_server *server) nogil + char* grpc_channelz_get_top_channels(intptr_t start_channel_id) + char* grpc_channelz_get_servers(intptr_t start_server_id) + char* grpc_channelz_get_server(intptr_t server_id) + char* grpc_channelz_get_server_sockets(intptr_t server_id, + intptr_t start_socket_id) + char* grpc_channelz_get_channel(intptr_t channel_id) + char* grpc_channelz_get_subchannel(intptr_t subchannel_id) + char* grpc_channelz_get_socket(intptr_t socket_id) + cdef extern from "grpc/grpc_security.h": diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx index ae5c07bfc82..9ab919375c0 100644 --- a/src/python/grpcio/grpc/_cython/cygrpc.pyx +++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx @@ -35,6 +35,7 @@ include "_cygrpc/server.pyx.pxi" include "_cygrpc/tag.pyx.pxi" include "_cygrpc/time.pyx.pxi" include "_cygrpc/_hooks.pyx.pxi" +include "_cygrpc/channelz.pyx.pxi" include "_cygrpc/grpc_gevent.pyx.pxi" diff --git a/src/python/grpcio_channelz/.gitignore b/src/python/grpcio_channelz/.gitignore new file mode 100644 index 00000000000..0c5da6b5af1 --- /dev/null +++ b/src/python/grpcio_channelz/.gitignore @@ -0,0 +1,6 @@ +*.proto +*_pb2.py +*_pb2_grpc.py +build/ +grpcio_channelz.egg-info/ +dist/ diff --git a/src/python/grpcio_channelz/MANIFEST.in b/src/python/grpcio_channelz/MANIFEST.in new file mode 100644 index 00000000000..5597f375ba6 --- /dev/null +++ b/src/python/grpcio_channelz/MANIFEST.in @@ -0,0 +1,3 @@ +include grpc_version.py +recursive-include grpc_channelz *.py +global-exclude *.pyc diff --git a/src/python/grpcio_channelz/README.rst b/src/python/grpcio_channelz/README.rst new file mode 100644 index 00000000000..efeaa560646 --- /dev/null +++ b/src/python/grpcio_channelz/README.rst @@ -0,0 +1,9 @@ +gRPC Python Channelz package +============================== + +Channelz is a live debug tool in gRPC Python. + +Dependencies +------------ + +Depends on the `grpcio` package, available from PyPI via `pip install grpcio`. diff --git a/src/python/grpcio_channelz/channelz_commands.py b/src/python/grpcio_channelz/channelz_commands.py new file mode 100644 index 00000000000..e9ad3550340 --- /dev/null +++ b/src/python/grpcio_channelz/channelz_commands.py @@ -0,0 +1,63 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Provides distutils command classes for the GRPC Python setup process.""" + +import os +import shutil + +import setuptools + +ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) +CHANNELZ_PROTO = os.path.join(ROOT_DIR, + '../../proto/grpc/channelz/channelz.proto') + + +class CopyProtoModules(setuptools.Command): + """Command to copy proto modules from grpc/src/proto.""" + + description = '' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + if os.path.isfile(CHANNELZ_PROTO): + shutil.copyfile(CHANNELZ_PROTO, + os.path.join(ROOT_DIR, + 'grpc_channelz/v1/channelz.proto')) + + +class BuildPackageProtos(setuptools.Command): + """Command to generate project *_pb2.py modules from proto files.""" + + description = 'build grpc protobuf modules' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + # due to limitations of the proto generator, we require that only *one* + # directory is provided as an 'include' directory. We assume it's the '' key + # to `self.distribution.package_dir` (and get a key error if it's not + # there). + from grpc_tools import command + command.build_package_protos(self.distribution.package_dir['']) diff --git a/src/python/grpcio_channelz/grpc_channelz/__init__.py b/src/python/grpcio_channelz/grpc_channelz/__init__.py new file mode 100644 index 00000000000..38fdfc9c5cf --- /dev/null +++ b/src/python/grpcio_channelz/grpc_channelz/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/python/grpcio_channelz/grpc_channelz/v1/BUILD.bazel b/src/python/grpcio_channelz/grpc_channelz/v1/BUILD.bazel new file mode 100644 index 00000000000..aae8cedb760 --- /dev/null +++ b/src/python/grpcio_channelz/grpc_channelz/v1/BUILD.bazel @@ -0,0 +1,38 @@ +load("@grpc_python_dependencies//:requirements.bzl", "requirement") +load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") + +package(default_visibility = ["//visibility:public"]) + +genrule( + name = "mv_channelz_proto", + srcs = [ + "//src/proto/grpc/channelz:channelz_proto_file", + ], + outs = ["channelz.proto",], + cmd = "cp $< $@", +) + +py_proto_library( + name = "py_channelz_proto", + protos = ["mv_channelz_proto",], + imports = [ + "external/com_google_protobuf/src/", + ], + inputs = [ + "@com_google_protobuf//:well_known_protos", + ], + with_grpc = True, + deps = [ + requirement('protobuf'), + ], +) + +py_library( + name = "grpc_channelz", + srcs = ["channelz.py",], + deps = [ + ":py_channelz_proto", + "//src/python/grpcio/grpc:grpcio", + ], + imports=["../../",], +) diff --git a/src/python/grpcio_channelz/grpc_channelz/v1/__init__.py b/src/python/grpcio_channelz/grpc_channelz/v1/__init__.py new file mode 100644 index 00000000000..38fdfc9c5cf --- /dev/null +++ b/src/python/grpcio_channelz/grpc_channelz/v1/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py b/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py new file mode 100644 index 00000000000..573b9d0d5ac --- /dev/null +++ b/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py @@ -0,0 +1,141 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Channelz debug service implementation in gRPC Python.""" + +import grpc +from grpc._cython import cygrpc + +import grpc_channelz.v1.channelz_pb2 as _channelz_pb2 +import grpc_channelz.v1.channelz_pb2_grpc as _channelz_pb2_grpc + +from google.protobuf import json_format + + +class ChannelzServicer(_channelz_pb2_grpc.ChannelzServicer): + """Servicer handling RPCs for service statuses.""" + + @staticmethod + def GetTopChannels(request, context): + try: + return json_format.Parse( + cygrpc.channelz_get_top_channels(request.start_channel_id), + _channelz_pb2.GetTopChannelsResponse(), + ) + except (ValueError, json_format.ParseError) as e: + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(str(e)) + + @staticmethod + def GetServers(request, context): + try: + return json_format.Parse( + cygrpc.channelz_get_servers(request.start_server_id), + _channelz_pb2.GetServersResponse(), + ) + except (ValueError, json_format.ParseError) as e: + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(str(e)) + + @staticmethod + def GetServer(request, context): + try: + return json_format.Parse( + cygrpc.channelz_get_server(request.server_id), + _channelz_pb2.GetServerResponse(), + ) + except ValueError as e: + context.set_code(grpc.StatusCode.NOT_FOUND) + context.set_details(str(e)) + except json_format.ParseError as e: + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(str(e)) + + @staticmethod + def GetServerSockets(request, context): + try: + return json_format.Parse( + cygrpc.channelz_get_server_sockets(request.server_id, + request.start_socket_id), + _channelz_pb2.GetServerSocketsResponse(), + ) + except ValueError as e: + context.set_code(grpc.StatusCode.NOT_FOUND) + context.set_details(str(e)) + except json_format.ParseError as e: + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(str(e)) + + @staticmethod + def GetChannel(request, context): + try: + return json_format.Parse( + cygrpc.channelz_get_channel(request.channel_id), + _channelz_pb2.GetChannelResponse(), + ) + except ValueError as e: + context.set_code(grpc.StatusCode.NOT_FOUND) + context.set_details(str(e)) + except json_format.ParseError as e: + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(str(e)) + + @staticmethod + def GetSubchannel(request, context): + try: + return json_format.Parse( + cygrpc.channelz_get_subchannel(request.subchannel_id), + _channelz_pb2.GetSubchannelResponse(), + ) + except ValueError as e: + context.set_code(grpc.StatusCode.NOT_FOUND) + context.set_details(str(e)) + except json_format.ParseError as e: + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(str(e)) + + @staticmethod + def GetSocket(request, context): + try: + return json_format.Parse( + cygrpc.channelz_get_socket(request.socket_id), + _channelz_pb2.GetSocketResponse(), + ) + except ValueError as e: + context.set_code(grpc.StatusCode.NOT_FOUND) + context.set_details(str(e)) + except json_format.ParseError as e: + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(str(e)) + + +def add_channelz_servicer(server): + """Add Channelz servicer to a server. Channelz servicer is in charge of + pulling information from C-Core for entire process. It will allow the + server to response to Channelz queries. + + The Channelz statistic is enabled by default inside C-Core. Whether the + statistic is enabled or not is isolated from adding Channelz servicer. + That means you can query Channelz info with a Channelz-disabled channel, + and you can add Channelz servicer to a Channelz-disabled server. + + The Channelz statistic can be enabled or disabled by channel option + 'grpc.enable_channelz'. Set to 1 to enable, set to 0 to disable. + + This is an EXPERIMENTAL API. + + Args: + server: grpc.Server to which Channelz service will be added. + """ + _channelz_pb2_grpc.add_ChannelzServicer_to_server(ChannelzServicer(), + server) diff --git a/src/python/grpcio_channelz/grpc_version.py b/src/python/grpcio_channelz/grpc_version.py new file mode 100644 index 00000000000..16356ea4020 --- /dev/null +++ b/src/python/grpcio_channelz/grpc_version.py @@ -0,0 +1,17 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_channelz/grpc_version.py.template`!!! + +VERSION = '1.18.0.dev0' diff --git a/src/python/grpcio_channelz/setup.py b/src/python/grpcio_channelz/setup.py new file mode 100644 index 00000000000..a495052376d --- /dev/null +++ b/src/python/grpcio_channelz/setup.py @@ -0,0 +1,96 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Setup module for the GRPC Python package's Channelz.""" + +import os +import sys + +import setuptools + +# Ensure we're in the proper directory whether or not we're being used by pip. +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +# Break import-style to ensure we can actually find our local modules. +import grpc_version + + +class _NoOpCommand(setuptools.Command): + """No-op command.""" + + description = '' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + pass + + +CLASSIFIERS = [ + 'Development Status :: 5 - Production/Stable', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'License :: OSI Approved :: Apache Software License', +] + +PACKAGE_DIRECTORIES = { + '': '.', +} + +INSTALL_REQUIRES = ( + 'protobuf>=3.6.0', + 'grpcio>={version}'.format(version=grpc_version.VERSION), +) + +try: + import channelz_commands as _channelz_commands + # we are in the build environment, otherwise the above import fails + SETUP_REQUIRES = ( + 'grpcio-tools=={version}'.format(version=grpc_version.VERSION),) + COMMAND_CLASS = { + # Run preprocess from the repository *before* doing any packaging! + 'preprocess': _channelz_commands.CopyProtoModules, + 'build_package_protos': _channelz_commands.BuildPackageProtos, + } +except ImportError: + SETUP_REQUIRES = () + COMMAND_CLASS = { + # wire up commands to no-op not to break the external dependencies + 'preprocess': _NoOpCommand, + 'build_package_protos': _NoOpCommand, + } + +setuptools.setup( + name='grpcio-channelz', + version=grpc_version.VERSION, + license='Apache License 2.0', + description='Channel Level Live Debug Information Service for gRPC', + author='The gRPC Authors', + author_email='grpc-io@googlegroups.com', + classifiers=CLASSIFIERS, + url='https://grpc.io', + package_dir=PACKAGE_DIRECTORIES, + packages=setuptools.find_packages('.'), + install_requires=INSTALL_REQUIRES, + setup_requires=SETUP_REQUIRES, + cmdclass=COMMAND_CLASS) diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py index d163f6fb68e..65e9a99950e 100644 --- a/src/python/grpcio_tests/commands.py +++ b/src/python/grpcio_tests/commands.py @@ -132,7 +132,12 @@ class TestGevent(setuptools.Command): 'unit.beta._beta_features_test', # TODO(https://github.com/grpc/grpc/issues/15411) unpin gevent version # This test will stuck while running higher version of gevent - 'unit._auth_context_test.AuthContextTest.testSessionResumption') + 'unit._auth_context_test.AuthContextTest.testSessionResumption', + # TODO(https://github.com/grpc/grpc/issues/17330) enable these three tests + 'channelz._channelz_servicer_test.ChannelzServicerTest.test_many_subchannels', + 'channelz._channelz_servicer_test.ChannelzServicerTest.test_many_subchannels_and_sockets', + 'channelz._channelz_servicer_test.ChannelzServicerTest.test_streaming_rpc' + ) description = 'run tests with gevent. Assumes grpc/gevent are installed' user_options = [] diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py index 61c98fa038b..f56425ac6d3 100644 --- a/src/python/grpcio_tests/setup.py +++ b/src/python/grpcio_tests/setup.py @@ -39,6 +39,7 @@ PACKAGE_DIRECTORIES = { INSTALL_REQUIRES = ( 'coverage>=4.0', 'enum34>=1.0.4', 'grpcio>={version}'.format(version=grpc_version.VERSION), + 'grpcio-channelz>={version}'.format(version=grpc_version.VERSION), 'grpcio-tools>={version}'.format(version=grpc_version.VERSION), 'grpcio-health-checking>={version}'.format(version=grpc_version.VERSION), 'oauth2client>=1.4.7', 'protobuf>=3.6.0', 'six>=1.10', 'google-auth>=1.0.0', diff --git a/src/python/grpcio_tests/tests/channelz/BUILD.bazel b/src/python/grpcio_tests/tests/channelz/BUILD.bazel new file mode 100644 index 00000000000..63513616e77 --- /dev/null +++ b/src/python/grpcio_tests/tests/channelz/BUILD.bazel @@ -0,0 +1,15 @@ +package(default_visibility = ["//visibility:public"]) + +py_test( + name = "channelz_servicer_test", + srcs = ["_channelz_servicer_test.py"], + main = "_channelz_servicer_test.py", + size = "small", + deps = [ + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_channelz/grpc_channelz/v1:grpc_channelz", + "//src/python/grpcio_tests/tests/unit:test_common", + "//src/python/grpcio_tests/tests/unit/framework/common:common", + ], + imports = ["../../",], +) diff --git a/src/python/grpcio_tests/tests/channelz/__init__.py b/src/python/grpcio_tests/tests/channelz/__init__.py new file mode 100644 index 00000000000..38fdfc9c5cf --- /dev/null +++ b/src/python/grpcio_tests/tests/channelz/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py b/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py new file mode 100644 index 00000000000..84f85946896 --- /dev/null +++ b/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py @@ -0,0 +1,494 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests of grpc_channelz.v1.channelz.""" + +import unittest + +from concurrent import futures + +import grpc +from grpc_channelz.v1 import channelz +from grpc_channelz.v1 import channelz_pb2 +from grpc_channelz.v1 import channelz_pb2_grpc + +from tests.unit import test_common +from tests.unit.framework.common import test_constants + +_SUCCESSFUL_UNARY_UNARY = '/test/SuccessfulUnaryUnary' +_FAILED_UNARY_UNARY = '/test/FailedUnaryUnary' +_SUCCESSFUL_STREAM_STREAM = '/test/SuccessfulStreamStream' + +_REQUEST = b'\x00\x00\x00' +_RESPONSE = b'\x01\x01\x01' + +_DISABLE_REUSE_PORT = (('grpc.so_reuseport', 0),) +_ENABLE_CHANNELZ = (('grpc.enable_channelz', 1),) +_DISABLE_CHANNELZ = (('grpc.enable_channelz', 0),) + + +def _successful_unary_unary(request, servicer_context): + return _RESPONSE + + +def _failed_unary_unary(request, servicer_context): + servicer_context.set_code(grpc.StatusCode.INTERNAL) + servicer_context.set_details("Channelz Test Intended Failure") + + +def _successful_stream_stream(request_iterator, servicer_context): + for _ in request_iterator: + yield _RESPONSE + + +class _GenericHandler(grpc.GenericRpcHandler): + + def service(self, handler_call_details): + if handler_call_details.method == _SUCCESSFUL_UNARY_UNARY: + return grpc.unary_unary_rpc_method_handler(_successful_unary_unary) + elif handler_call_details.method == _FAILED_UNARY_UNARY: + return grpc.unary_unary_rpc_method_handler(_failed_unary_unary) + elif handler_call_details.method == _SUCCESSFUL_STREAM_STREAM: + return grpc.stream_stream_rpc_method_handler( + _successful_stream_stream) + else: + return None + + +class _ChannelServerPair(object): + + def __init__(self): + # Server will enable channelz service + # Bind as attribute, so its `del` can be called explicitly, during + # the destruction process. Otherwise, if the removal of server + # rely on gc cycle, the test will become non-deterministic. + self._server = grpc.server( + futures.ThreadPoolExecutor(max_workers=3), + options=_DISABLE_REUSE_PORT + _ENABLE_CHANNELZ) + port = self._server.add_insecure_port('[::]:0') + self._server.add_generic_rpc_handlers((_GenericHandler(),)) + self._server.start() + + # Channel will enable channelz service... + self.channel = grpc.insecure_channel('localhost:%d' % port, + _ENABLE_CHANNELZ) + + def __del__(self): + self._server.__del__() + self.channel.close() + + +def _generate_channel_server_pairs(n): + return [_ChannelServerPair() for i in range(n)] + + +def _clean_channel_server_pairs(pairs): + for pair in pairs: + pair.__del__() + + +class ChannelzServicerTest(unittest.TestCase): + + def _send_successful_unary_unary(self, idx): + _, r = self._pairs[idx].channel.unary_unary( + _SUCCESSFUL_UNARY_UNARY).with_call(_REQUEST) + self.assertEqual(r.code(), grpc.StatusCode.OK) + + def _send_failed_unary_unary(self, idx): + try: + self._pairs[idx].channel.unary_unary(_FAILED_UNARY_UNARY).with_call( + _REQUEST) + except grpc.RpcError: + return + else: + self.fail("This call supposed to fail") + + def _send_successful_stream_stream(self, idx): + response_iterator = self._pairs[idx].channel.stream_stream( + _SUCCESSFUL_STREAM_STREAM).__call__( + iter([_REQUEST] * test_constants.STREAM_LENGTH)) + cnt = 0 + for _ in response_iterator: + cnt += 1 + self.assertEqual(cnt, test_constants.STREAM_LENGTH) + + def _get_channel_id(self, idx): + """Channel id may not be consecutive""" + resp = self._channelz_stub.GetTopChannels( + channelz_pb2.GetTopChannelsRequest(start_channel_id=0)) + self.assertGreater(len(resp.channel), idx) + return resp.channel[idx].ref.channel_id + + def setUp(self): + self._pairs = [] + # This server is for Channelz info fetching only + # It self should not enable Channelz + self._server = grpc.server( + futures.ThreadPoolExecutor(max_workers=3), + options=_DISABLE_REUSE_PORT + _DISABLE_CHANNELZ) + port = self._server.add_insecure_port('[::]:0') + channelz.add_channelz_servicer(self._server) + self._server.start() + + # This channel is used to fetch Channelz info only + # Channelz should not be enabled + self._channel = grpc.insecure_channel('localhost:%d' % port, + _DISABLE_CHANNELZ) + self._channelz_stub = channelz_pb2_grpc.ChannelzStub(self._channel) + + def tearDown(self): + self._server.__del__() + self._channel.close() + _clean_channel_server_pairs(self._pairs) + + def test_get_top_channels_basic(self): + self._pairs = _generate_channel_server_pairs(1) + resp = self._channelz_stub.GetTopChannels( + channelz_pb2.GetTopChannelsRequest(start_channel_id=0)) + self.assertEqual(len(resp.channel), 1) + self.assertEqual(resp.end, True) + + def test_get_top_channels_high_start_id(self): + self._pairs = _generate_channel_server_pairs(1) + resp = self._channelz_stub.GetTopChannels( + channelz_pb2.GetTopChannelsRequest(start_channel_id=10000)) + self.assertEqual(len(resp.channel), 0) + self.assertEqual(resp.end, True) + + def test_successful_request(self): + self._pairs = _generate_channel_server_pairs(1) + self._send_successful_unary_unary(0) + resp = self._channelz_stub.GetChannel( + channelz_pb2.GetChannelRequest(channel_id=self._get_channel_id(0))) + self.assertEqual(resp.channel.data.calls_started, 1) + self.assertEqual(resp.channel.data.calls_succeeded, 1) + self.assertEqual(resp.channel.data.calls_failed, 0) + + def test_failed_request(self): + self._pairs = _generate_channel_server_pairs(1) + self._send_failed_unary_unary(0) + resp = self._channelz_stub.GetChannel( + channelz_pb2.GetChannelRequest(channel_id=self._get_channel_id(0))) + self.assertEqual(resp.channel.data.calls_started, 1) + self.assertEqual(resp.channel.data.calls_succeeded, 0) + self.assertEqual(resp.channel.data.calls_failed, 1) + + def test_many_requests(self): + self._pairs = _generate_channel_server_pairs(1) + k_success = 7 + k_failed = 9 + for i in range(k_success): + self._send_successful_unary_unary(0) + for i in range(k_failed): + self._send_failed_unary_unary(0) + resp = self._channelz_stub.GetChannel( + channelz_pb2.GetChannelRequest(channel_id=self._get_channel_id(0))) + self.assertEqual(resp.channel.data.calls_started, k_success + k_failed) + self.assertEqual(resp.channel.data.calls_succeeded, k_success) + self.assertEqual(resp.channel.data.calls_failed, k_failed) + + def test_many_channel(self): + k_channels = 4 + self._pairs = _generate_channel_server_pairs(k_channels) + resp = self._channelz_stub.GetTopChannels( + channelz_pb2.GetTopChannelsRequest(start_channel_id=0)) + self.assertEqual(len(resp.channel), k_channels) + + def test_many_requests_many_channel(self): + k_channels = 4 + self._pairs = _generate_channel_server_pairs(k_channels) + k_success = 11 + k_failed = 13 + for i in range(k_success): + self._send_successful_unary_unary(0) + self._send_successful_unary_unary(2) + for i in range(k_failed): + self._send_failed_unary_unary(1) + self._send_failed_unary_unary(2) + + # The first channel saw only successes + resp = self._channelz_stub.GetChannel( + channelz_pb2.GetChannelRequest(channel_id=self._get_channel_id(0))) + self.assertEqual(resp.channel.data.calls_started, k_success) + self.assertEqual(resp.channel.data.calls_succeeded, k_success) + self.assertEqual(resp.channel.data.calls_failed, 0) + + # The second channel saw only failures + resp = self._channelz_stub.GetChannel( + channelz_pb2.GetChannelRequest(channel_id=self._get_channel_id(1))) + self.assertEqual(resp.channel.data.calls_started, k_failed) + self.assertEqual(resp.channel.data.calls_succeeded, 0) + self.assertEqual(resp.channel.data.calls_failed, k_failed) + + # The third channel saw both successes and failures + resp = self._channelz_stub.GetChannel( + channelz_pb2.GetChannelRequest(channel_id=self._get_channel_id(2))) + self.assertEqual(resp.channel.data.calls_started, k_success + k_failed) + self.assertEqual(resp.channel.data.calls_succeeded, k_success) + self.assertEqual(resp.channel.data.calls_failed, k_failed) + + # The fourth channel saw nothing + resp = self._channelz_stub.GetChannel( + channelz_pb2.GetChannelRequest(channel_id=self._get_channel_id(3))) + self.assertEqual(resp.channel.data.calls_started, 0) + self.assertEqual(resp.channel.data.calls_succeeded, 0) + self.assertEqual(resp.channel.data.calls_failed, 0) + + def test_many_subchannels(self): + k_channels = 4 + self._pairs = _generate_channel_server_pairs(k_channels) + k_success = 17 + k_failed = 19 + for i in range(k_success): + self._send_successful_unary_unary(0) + self._send_successful_unary_unary(2) + for i in range(k_failed): + self._send_failed_unary_unary(1) + self._send_failed_unary_unary(2) + + gtc_resp = self._channelz_stub.GetTopChannels( + channelz_pb2.GetTopChannelsRequest(start_channel_id=0)) + self.assertEqual(len(gtc_resp.channel), k_channels) + for i in range(k_channels): + # If no call performed in the channel, there shouldn't be any subchannel + if gtc_resp.channel[i].data.calls_started == 0: + self.assertEqual(len(gtc_resp.channel[i].subchannel_ref), 0) + continue + + # Otherwise, the subchannel should exist + self.assertGreater(len(gtc_resp.channel[i].subchannel_ref), 0) + gsc_resp = self._channelz_stub.GetSubchannel( + channelz_pb2.GetSubchannelRequest( + subchannel_id=gtc_resp.channel[i].subchannel_ref[ + 0].subchannel_id)) + self.assertEqual(gtc_resp.channel[i].data.calls_started, + gsc_resp.subchannel.data.calls_started) + self.assertEqual(gtc_resp.channel[i].data.calls_succeeded, + gsc_resp.subchannel.data.calls_succeeded) + self.assertEqual(gtc_resp.channel[i].data.calls_failed, + gsc_resp.subchannel.data.calls_failed) + + @unittest.skip('Servers in core are not guaranteed to be destroyed ' \ + 'immediately when the reference goes out of scope, so ' \ + 'servers from multiple test cases are not hermetic. ' \ + 'TODO(https://github.com/grpc/grpc/issues/17258)') + def test_server_basic(self): + self._pairs = _generate_channel_server_pairs(1) + resp = self._channelz_stub.GetServers( + channelz_pb2.GetServersRequest(start_server_id=0)) + self.assertEqual(len(resp.server), 1) + + @unittest.skip('Servers in core are not guaranteed to be destroyed ' \ + 'immediately when the reference goes out of scope, so ' \ + 'servers from multiple test cases are not hermetic. ' \ + 'TODO(https://github.com/grpc/grpc/issues/17258)') + def test_get_one_server(self): + self._pairs = _generate_channel_server_pairs(1) + gss_resp = self._channelz_stub.GetServers( + channelz_pb2.GetServersRequest(start_server_id=0)) + self.assertEqual(len(gss_resp.server), 1) + gs_resp = self._channelz_stub.GetServer( + channelz_pb2.GetServerRequest( + server_id=gss_resp.server[0].ref.server_id)) + self.assertEqual(gss_resp.server[0].ref.server_id, + gs_resp.server.ref.server_id) + + @unittest.skip('Servers in core are not guaranteed to be destroyed ' \ + 'immediately when the reference goes out of scope, so ' \ + 'servers from multiple test cases are not hermetic. ' \ + 'TODO(https://github.com/grpc/grpc/issues/17258)') + def test_server_call(self): + self._pairs = _generate_channel_server_pairs(1) + k_success = 23 + k_failed = 29 + for i in range(k_success): + self._send_successful_unary_unary(0) + for i in range(k_failed): + self._send_failed_unary_unary(0) + + resp = self._channelz_stub.GetServers( + channelz_pb2.GetServersRequest(start_server_id=0)) + self.assertEqual(len(resp.server), 1) + self.assertEqual(resp.server[0].data.calls_started, + k_success + k_failed) + self.assertEqual(resp.server[0].data.calls_succeeded, k_success) + self.assertEqual(resp.server[0].data.calls_failed, k_failed) + + def test_many_subchannels_and_sockets(self): + k_channels = 4 + self._pairs = _generate_channel_server_pairs(k_channels) + k_success = 3 + k_failed = 5 + for i in range(k_success): + self._send_successful_unary_unary(0) + self._send_successful_unary_unary(2) + for i in range(k_failed): + self._send_failed_unary_unary(1) + self._send_failed_unary_unary(2) + + gtc_resp = self._channelz_stub.GetTopChannels( + channelz_pb2.GetTopChannelsRequest(start_channel_id=0)) + self.assertEqual(len(gtc_resp.channel), k_channels) + for i in range(k_channels): + # If no call performed in the channel, there shouldn't be any subchannel + if gtc_resp.channel[i].data.calls_started == 0: + self.assertEqual(len(gtc_resp.channel[i].subchannel_ref), 0) + continue + + # Otherwise, the subchannel should exist + self.assertGreater(len(gtc_resp.channel[i].subchannel_ref), 0) + gsc_resp = self._channelz_stub.GetSubchannel( + channelz_pb2.GetSubchannelRequest( + subchannel_id=gtc_resp.channel[i].subchannel_ref[ + 0].subchannel_id)) + self.assertEqual(len(gsc_resp.subchannel.socket_ref), 1) + + gs_resp = self._channelz_stub.GetSocket( + channelz_pb2.GetSocketRequest( + socket_id=gsc_resp.subchannel.socket_ref[0].socket_id)) + self.assertEqual(gsc_resp.subchannel.data.calls_started, + gs_resp.socket.data.streams_started) + self.assertEqual(gsc_resp.subchannel.data.calls_started, + gs_resp.socket.data.streams_succeeded) + # Calls started == messages sent, only valid for unary calls + self.assertEqual(gsc_resp.subchannel.data.calls_started, + gs_resp.socket.data.messages_sent) + # Only receive responses when the RPC was successful + self.assertEqual(gsc_resp.subchannel.data.calls_succeeded, + gs_resp.socket.data.messages_received) + + def test_streaming_rpc(self): + self._pairs = _generate_channel_server_pairs(1) + # In C++, the argument for _send_successful_stream_stream is message length. + # Here the argument is still channel idx, to be consistent with the other two. + self._send_successful_stream_stream(0) + + gc_resp = self._channelz_stub.GetChannel( + channelz_pb2.GetChannelRequest(channel_id=self._get_channel_id(0))) + self.assertEqual(gc_resp.channel.data.calls_started, 1) + self.assertEqual(gc_resp.channel.data.calls_succeeded, 1) + self.assertEqual(gc_resp.channel.data.calls_failed, 0) + # Subchannel exists + self.assertGreater(len(gc_resp.channel.subchannel_ref), 0) + + gsc_resp = self._channelz_stub.GetSubchannel( + channelz_pb2.GetSubchannelRequest( + subchannel_id=gc_resp.channel.subchannel_ref[0].subchannel_id)) + self.assertEqual(gsc_resp.subchannel.data.calls_started, 1) + self.assertEqual(gsc_resp.subchannel.data.calls_succeeded, 1) + self.assertEqual(gsc_resp.subchannel.data.calls_failed, 0) + # Socket exists + self.assertEqual(len(gsc_resp.subchannel.socket_ref), 1) + + gs_resp = self._channelz_stub.GetSocket( + channelz_pb2.GetSocketRequest( + socket_id=gsc_resp.subchannel.socket_ref[0].socket_id)) + self.assertEqual(gs_resp.socket.data.streams_started, 1) + self.assertEqual(gs_resp.socket.data.streams_succeeded, 1) + self.assertEqual(gs_resp.socket.data.streams_failed, 0) + self.assertEqual(gs_resp.socket.data.messages_sent, + test_constants.STREAM_LENGTH) + self.assertEqual(gs_resp.socket.data.messages_received, + test_constants.STREAM_LENGTH) + + @unittest.skip('Servers in core are not guaranteed to be destroyed ' \ + 'immediately when the reference goes out of scope, so ' \ + 'servers from multiple test cases are not hermetic. ' \ + 'TODO(https://github.com/grpc/grpc/issues/17258)') + def test_server_sockets(self): + self._pairs = _generate_channel_server_pairs(1) + self._send_successful_unary_unary(0) + self._send_failed_unary_unary(0) + + gs_resp = self._channelz_stub.GetServers( + channelz_pb2.GetServersRequest(start_server_id=0)) + self.assertEqual(len(gs_resp.server), 1) + self.assertEqual(gs_resp.server[0].data.calls_started, 2) + self.assertEqual(gs_resp.server[0].data.calls_succeeded, 1) + self.assertEqual(gs_resp.server[0].data.calls_failed, 1) + + gss_resp = self._channelz_stub.GetServerSockets( + channelz_pb2.GetServerSocketsRequest( + server_id=gs_resp.server[0].ref.server_id, start_socket_id=0)) + # If the RPC call failed, it will raise a grpc.RpcError + # So, if there is no exception raised, considered pass + + @unittest.skip('Servers in core are not guaranteed to be destroyed ' \ + 'immediately when the reference goes out of scope, so ' \ + 'servers from multiple test cases are not hermetic. ' \ + 'TODO(https://github.com/grpc/grpc/issues/17258)') + def test_server_listen_sockets(self): + self._pairs = _generate_channel_server_pairs(1) + + gss_resp = self._channelz_stub.GetServers( + channelz_pb2.GetServersRequest(start_server_id=0)) + self.assertEqual(len(gss_resp.server), 1) + self.assertEqual(len(gss_resp.server[0].listen_socket), 1) + + gs_resp = self._channelz_stub.GetSocket( + channelz_pb2.GetSocketRequest( + socket_id=gss_resp.server[0].listen_socket[0].socket_id)) + # If the RPC call failed, it will raise a grpc.RpcError + # So, if there is no exception raised, considered pass + + def test_invalid_query_get_server(self): + try: + self._channelz_stub.GetServer( + channelz_pb2.GetServerRequest(server_id=10000)) + except BaseException as e: + self.assertIn('StatusCode.NOT_FOUND', str(e)) + else: + self.fail('Invalid query not detected') + + def test_invalid_query_get_channel(self): + try: + self._channelz_stub.GetChannel( + channelz_pb2.GetChannelRequest(channel_id=10000)) + except BaseException as e: + self.assertIn('StatusCode.NOT_FOUND', str(e)) + else: + self.fail('Invalid query not detected') + + def test_invalid_query_get_subchannel(self): + try: + self._channelz_stub.GetSubchannel( + channelz_pb2.GetSubchannelRequest(subchannel_id=10000)) + except BaseException as e: + self.assertIn('StatusCode.NOT_FOUND', str(e)) + else: + self.fail('Invalid query not detected') + + def test_invalid_query_get_socket(self): + try: + self._channelz_stub.GetSocket( + channelz_pb2.GetSocketRequest(socket_id=10000)) + except BaseException as e: + self.assertIn('StatusCode.NOT_FOUND', str(e)) + else: + self.fail('Invalid query not detected') + + def test_invalid_query_get_server_sockets(self): + try: + self._channelz_stub.GetServerSockets( + channelz_pb2.GetServerSocketsRequest( + server_id=10000, + start_socket_id=0, + )) + except BaseException as e: + self.assertIn('StatusCode.NOT_FOUND', str(e)) + else: + self.fail('Invalid query not detected') + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json index a3006d9afc2..9cffd3df197 100644 --- a/src/python/grpcio_tests/tests/tests.json +++ b/src/python/grpcio_tests/tests/tests.json @@ -1,5 +1,6 @@ [ "_sanity._sanity_test.SanityTest", + "channelz._channelz_servicer_test.ChannelzServicerTest", "health_check._health_servicer_test.HealthServicerTest", "interop._insecure_intraop_test.InsecureIntraopTest", "interop._secure_intraop_test.SecureIntraopTest", diff --git a/src/ruby/pb/grpc/health/checker.rb b/src/ruby/pb/grpc/health/checker.rb index c492455d8ff..7ad68409dd4 100644 --- a/src/ruby/pb/grpc/health/checker.rb +++ b/src/ruby/pb/grpc/health/checker.rb @@ -14,7 +14,6 @@ require 'grpc' require 'grpc/health/v1/health_services_pb' -require 'thread' module Grpc # Health contains classes and modules that support providing a health check @@ -37,9 +36,9 @@ module Grpc @status_mutex.synchronize do status = @statuses["#{req.service}"] end - if status.nil? + if status.nil? fail GRPC::BadStatus.new_status_exception(StatusCodes::NOT_FOUND) - end + end HealthCheckResponse.new(status: status) end diff --git a/templates/src/python/grpcio_channelz/grpc_version.py.template b/templates/src/python/grpcio_channelz/grpc_version.py.template new file mode 100644 index 00000000000..75d510cd17b --- /dev/null +++ b/templates/src/python/grpcio_channelz/grpc_version.py.template @@ -0,0 +1,19 @@ +%YAML 1.2 +--- | + # Copyright 2018 The gRPC Authors + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + + # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_channelz/grpc_version.py.template`!!! + + VERSION = '${settings.python_version.pep440()}' diff --git a/templates/tools/dockerfile/csharp_deps.include b/templates/tools/dockerfile/csharp_deps.include index 7ed00748670..fdede9e840b 100644 --- a/templates/tools/dockerfile/csharp_deps.include +++ b/templates/tools/dockerfile/csharp_deps.include @@ -1,24 +1,15 @@ #================ # C# dependencies -# Update to a newer version of mono -RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF -RUN echo "deb http://download.mono-project.com/repo/debian jessie main" | tee /etc/apt/sources.list.d/mono-official.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list - -# Install dependencies -RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y ${'\\'} +# cmake >=3.6 needed to build grpc_csharp_ext +RUN apt-get update && apt-get install -y cmake && apt-get clean + +# Install mono +RUN apt-get update && apt-get install -y apt-transport-https dirmngr && apt-get clean +RUN apt-key adv --no-tty --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF +RUN echo "deb https://download.mono-project.com/repo/debian stable-stretch main" | tee /etc/apt/sources.list.d/mono-official-stable.list +RUN apt-get update && apt-get install -y ${'\\'} mono-devel ${'\\'} ca-certificates-mono ${'\\'} nuget ${'\\'} && apt-get clean - -RUN nuget update -self - -#================= -# Use cmake 3.6 from jessie-backports -# needed to build grpc_csharp_ext with cmake - -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean diff --git a/templates/tools/dockerfile/csharp_dotnetcli_deps.include b/templates/tools/dockerfile/csharp_dotnetcli_deps.include index bc88d2bfa39..f3335926402 100644 --- a/templates/tools/dockerfile/csharp_dotnetcli_deps.include +++ b/templates/tools/dockerfile/csharp_dotnetcli_deps.include @@ -1,12 +1,20 @@ -# Install dotnet SDK based on https://www.microsoft.com/net/core#debian -RUN apt-get update && apt-get install -y curl libunwind8 gettext -# dotnet-dev-1.0.0-preview2-003131 -RUN curl -sSL -o dotnet100.tar.gz https://go.microsoft.com/fwlink/?LinkID=827530 -RUN mkdir -p /opt/dotnet && tar zxf dotnet100.tar.gz -C /opt/dotnet -# dotnet-dev-1.0.1 -RUN curl -sSL -o dotnet101.tar.gz https://go.microsoft.com/fwlink/?LinkID=843453 -RUN mkdir -p /opt/dotnet && tar zxf dotnet101.tar.gz -C /opt/dotnet -RUN ln -s /opt/dotnet/dotnet /usr/local/bin +# Install dotnet SDK +ENV DOTNET_SDK_VERSION 2.1.500 +RUN curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$DOTNET_SDK_VERSION/dotnet-sdk-$DOTNET_SDK_VERSION-linux-x64.tar.gz ${'\\'} + && mkdir -p /usr/share/dotnet ${'\\'} + && tar -zxf dotnet.tar.gz -C /usr/share/dotnet ${'\\'} + && rm dotnet.tar.gz ${'\\'} + && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet + + +# Install .NET Core 1.1.10 runtime (required to run netcoreapp1.1) +RUN curl -sSL -o dotnet_old.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/1.1.10/dotnet-debian.9-x64.1.1.10.tar.gz ${'\\'} + && mkdir -p dotnet_old ${'\\'} + && tar zxf dotnet_old.tar.gz -C dotnet_old ${'\\'} + && cp -r dotnet_old/shared/Microsoft.NETCore.App/1.1.10/ /usr/share/dotnet/shared/Microsoft.NETCore.App/ ${'\\'} + && rm -rf dotnet_old/ dotnet_old.tar.gz +RUN apt-get update && apt-get install -y libunwind8 && apt-get clean + # Trigger the population of the local package cache ENV NUGET_XMLDOC_MODE skip diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile.template index a1f1283de0f..abf1a3853d3 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + FROM debian:stretch <%include file="../../apt_get_basic.include"/> <%include file="../../python_deps.include"/> diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile.template index a1f1283de0f..abf1a3853d3 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + FROM debian:stretch <%include file="../../apt_get_basic.include"/> <%include file="../../python_deps.include"/> diff --git a/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/csharp_stretch_x64/Dockerfile.template similarity index 94% rename from templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template rename to templates/tools/dockerfile/test/csharp_stretch_x64/Dockerfile.template index 432f05442c2..1526d07fc63 100644 --- a/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/csharp_stretch_x64/Dockerfile.template @@ -1,6 +1,6 @@ %YAML 1.2 --- | - # Copyright 2015 gRPC authors. + # Copyright 2018 The gRPC Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + FROM debian:stretch <%include file="../../apt_get_basic.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/test/core/avl/avl_test.cc b/test/core/avl/avl_test.cc index 01002fec72a..769e67563dc 100644 --- a/test/core/avl/avl_test.cc +++ b/test/core/avl/avl_test.cc @@ -283,7 +283,7 @@ static void test_stress(int amount_of_stress) { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_get(); test_ll(); diff --git a/test/core/backoff/backoff_test.cc b/test/core/backoff/backoff_test.cc index 1998a839778..8fd120e0428 100644 --- a/test/core/backoff/backoff_test.cc +++ b/test/core/backoff/backoff_test.cc @@ -171,7 +171,7 @@ TEST(BackOffTest, JitterBackOff) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/bad_client/tests/badreq.cc b/test/core/bad_client/tests/badreq.cc index eeaf4c99748..c560dc5561c 100644 --- a/test/core/bad_client/tests/badreq.cc +++ b/test/core/bad_client/tests/badreq.cc @@ -39,7 +39,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* invalid content type */ diff --git a/test/core/bad_client/tests/connection_prefix.cc b/test/core/bad_client/tests/connection_prefix.cc index 4aab234d3e5..286a3ccafbb 100644 --- a/test/core/bad_client/tests/connection_prefix.cc +++ b/test/core/bad_client/tests/connection_prefix.cc @@ -29,7 +29,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, "X", 0); diff --git a/test/core/bad_client/tests/duplicate_header.cc b/test/core/bad_client/tests/duplicate_header.cc index e3cae8b5952..dfa6e518114 100644 --- a/test/core/bad_client/tests/duplicate_header.cc +++ b/test/core/bad_client/tests/duplicate_header.cc @@ -122,7 +122,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* Verify that sending multiple headers doesn't segfault */ diff --git a/test/core/bad_client/tests/head_of_line_blocking.cc b/test/core/bad_client/tests/head_of_line_blocking.cc index 427db464462..c856b9b122c 100644 --- a/test/core/bad_client/tests/head_of_line_blocking.cc +++ b/test/core/bad_client/tests/head_of_line_blocking.cc @@ -109,7 +109,7 @@ static void addbuf(const void* data, size_t len) { int main(int argc, char** argv) { int i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); #define NUM_FRAMES 10 diff --git a/test/core/bad_client/tests/headers.cc b/test/core/bad_client/tests/headers.cc index 2aa1b280cee..02ea7597502 100644 --- a/test/core/bad_client/tests/headers.cc +++ b/test/core/bad_client/tests/headers.cc @@ -33,7 +33,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* partial http2 header prefixes */ diff --git a/test/core/bad_client/tests/initial_settings_frame.cc b/test/core/bad_client/tests/initial_settings_frame.cc index 0220000ecea..fcbb841331f 100644 --- a/test/core/bad_client/tests/initial_settings_frame.cc +++ b/test/core/bad_client/tests/initial_settings_frame.cc @@ -32,7 +32,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* various partial prefixes */ diff --git a/test/core/bad_client/tests/large_metadata.cc b/test/core/bad_client/tests/large_metadata.cc index d534753f536..520a1af0c2d 100644 --- a/test/core/bad_client/tests/large_metadata.cc +++ b/test/core/bad_client/tests/large_metadata.cc @@ -141,7 +141,7 @@ static void server_verifier_sends_too_much_metadata(grpc_server* server, int main(int argc, char** argv) { int i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); // Test sending more metadata than the server will accept. gpr_strvec headers; diff --git a/test/core/bad_client/tests/server_registered_method.cc b/test/core/bad_client/tests/server_registered_method.cc index c2dc9c66af1..834142ac1b4 100644 --- a/test/core/bad_client/tests/server_registered_method.cc +++ b/test/core/bad_client/tests/server_registered_method.cc @@ -76,7 +76,7 @@ static void verifier_fails(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* body generated with diff --git a/test/core/bad_client/tests/simple_request.cc b/test/core/bad_client/tests/simple_request.cc index c80fc5cb4af..34049aaaffc 100644 --- a/test/core/bad_client/tests/simple_request.cc +++ b/test/core/bad_client/tests/simple_request.cc @@ -123,7 +123,7 @@ static void failure_verifier(grpc_server* server, grpc_completion_queue* cq, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* basic request: check that things are working */ diff --git a/test/core/bad_client/tests/unknown_frame.cc b/test/core/bad_client/tests/unknown_frame.cc index b1b618a43f3..9e0cf3f6a90 100644 --- a/test/core/bad_client/tests/unknown_frame.cc +++ b/test/core/bad_client/tests/unknown_frame.cc @@ -34,7 +34,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq, int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* test adding prioritization data */ GRPC_RUN_BAD_CLIENT_TEST(verifier, nullptr, diff --git a/test/core/bad_client/tests/window_overflow.cc b/test/core/bad_client/tests/window_overflow.cc index b552704e9c5..87042a46f20 100644 --- a/test/core/bad_client/tests/window_overflow.cc +++ b/test/core/bad_client/tests/window_overflow.cc @@ -71,7 +71,7 @@ int main(int argc, char** argv) { #define FRAME_SIZE (MESSAGES_PER_FRAME * 5) #define SEND_SIZE (4 * 1024 * 1024) #define NUM_FRAMES (SEND_SIZE / FRAME_SIZE + 1) - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); addbuf(PFX_STR, sizeof(PFX_STR) - 1); diff --git a/test/core/channel/channel_args_test.cc b/test/core/channel/channel_args_test.cc index 41c62a8f16e..087a7679bf8 100644 --- a/test/core/channel/channel_args_test.cc +++ b/test/core/channel/channel_args_test.cc @@ -231,7 +231,7 @@ static void test_server_create_with_args(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_create(); test_set_compression_algorithm(); diff --git a/test/core/channel/channel_stack_builder_test.cc b/test/core/channel/channel_stack_builder_test.cc index aad6d6eee9a..b5598e63f9f 100644 --- a/test/core/channel/channel_stack_builder_test.cc +++ b/test/core/channel/channel_stack_builder_test.cc @@ -132,7 +132,7 @@ static void init_plugin(void) { static void destroy_plugin(void) {} int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_register_plugin(init_plugin, destroy_plugin); grpc_init(); test_channel_stack_builder_filter_replace(); diff --git a/test/core/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc index 6f0bfa06d21..14726336f92 100644 --- a/test/core/channel/channel_stack_test.cc +++ b/test/core/channel/channel_stack_test.cc @@ -147,7 +147,7 @@ static void test_create_channel_stack(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_create_channel_stack(); grpc_shutdown(); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 3d8de79e376..b3c0b368982 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -342,7 +342,7 @@ TEST(ChannelTracerTest, TestTotalEviction) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc index fdfc8eec94a..ed3d629dc99 100644 --- a/test/core/channel/channelz_registry_test.cc +++ b/test/core/channel/channelz_registry_test.cc @@ -195,7 +195,7 @@ TEST_F(ChannelzRegistryTest, TestAddAfterCompaction) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 4d4b0770022..abd1601ad14 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -541,7 +541,7 @@ INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest, } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); diff --git a/test/core/channel/minimal_stack_is_minimal_test.cc b/test/core/channel/minimal_stack_is_minimal_test.cc index e5953acedcf..bee0bfb41f2 100644 --- a/test/core/channel/minimal_stack_is_minimal_test.cc +++ b/test/core/channel/minimal_stack_is_minimal_test.cc @@ -56,7 +56,7 @@ static int check_stack(const char* file, int line, const char* transport_name, #define CHECK_STACK(...) check_stack(__FILE__, __LINE__, __VA_ARGS__) int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); int errors = 0; diff --git a/test/core/client_channel/parse_address_test.cc b/test/core/client_channel/parse_address_test.cc index 004549fa621..b77a51a9e49 100644 --- a/test/core/client_channel/parse_address_test.cc +++ b/test/core/client_channel/parse_address_test.cc @@ -101,7 +101,7 @@ static void test_grpc_parse_ipv6_invalid(const char* uri_text) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_grpc_parse_unix("unix:/path/name", "/path/name"); diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc index eb5a9117484..76769b2b64a 100644 --- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc @@ -64,7 +64,7 @@ static grpc_ares_request* my_dns_lookup_ares_locked( const char* dns_server, const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** lb_addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout_ms, grpc_combiner* combiner) { gpr_mu_lock(&g_mu); GPR_ASSERT(0 == strcmp("test", addr)); grpc_error* error = GRPC_ERROR_NONE; @@ -145,7 +145,7 @@ static void call_resolver_next_after_locking(grpc_core::Resolver* resolver, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); gpr_mu_init(&g_mu); diff --git a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc index 1a7db40f598..cdbe33dbe79 100644 --- a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc @@ -41,7 +41,7 @@ static grpc_ares_request* (*g_default_dns_lookup_ares_locked)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner); + int query_timeout_ms, grpc_combiner* combiner); // Counter incremented by test_resolve_address_impl indicating the number of // times a system-level resolution has happened. @@ -91,10 +91,10 @@ static grpc_ares_request* test_dns_lookup_ares_locked( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout_ms, grpc_combiner* combiner) { grpc_ares_request* result = g_default_dns_lookup_ares_locked( dns_server, name, default_port, g_iomgr_args.pollset_set, on_done, addrs, - check_grpclb, service_config_json, combiner); + check_grpclb, service_config_json, query_timeout_ms, combiner); ++g_resolution_count; static grpc_millis last_resolution_time = 0; if (last_resolution_time == 0) { @@ -262,7 +262,7 @@ static void test_cooldown() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); g_combiner = grpc_combiner_create(); diff --git a/test/core/client_channel/resolvers/dns_resolver_test.cc b/test/core/client_channel/resolvers/dns_resolver_test.cc index 103b2916c46..571746abe86 100644 --- a/test/core/client_channel/resolvers/dns_resolver_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_test.cc @@ -60,7 +60,7 @@ static void test_fails(grpc_core::ResolverFactory* factory, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); g_combiner = grpc_combiner_create(); diff --git a/test/core/client_channel/resolvers/fake_resolver_test.cc b/test/core/client_channel/resolvers/fake_resolver_test.cc index f6696bf1278..6362b95e50e 100644 --- a/test/core/client_channel/resolvers/fake_resolver_test.cc +++ b/test/core/client_channel/resolvers/fake_resolver_test.cc @@ -213,7 +213,7 @@ static void test_fake_resolver() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_fake_resolver(); diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.cc b/test/core/client_channel/resolvers/sockaddr_resolver_test.cc index b9287c24688..ff7db6046d7 100644 --- a/test/core/client_channel/resolvers/sockaddr_resolver_test.cc +++ b/test/core/client_channel/resolvers/sockaddr_resolver_test.cc @@ -84,7 +84,7 @@ static void test_fails(grpc_core::ResolverFactory* factory, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); g_combiner = grpc_combiner_create(); diff --git a/test/core/client_channel/retry_throttle_test.cc b/test/core/client_channel/retry_throttle_test.cc index c6d5d3ebbb8..793e86dc065 100644 --- a/test/core/client_channel/retry_throttle_test.cc +++ b/test/core/client_channel/retry_throttle_test.cc @@ -136,7 +136,7 @@ TEST(ServerRetryThrottleMap, Replacement) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/client_channel/uri_parser_test.cc b/test/core/client_channel/uri_parser_test.cc index ec4f755dda8..713ec32e5e8 100644 --- a/test/core/client_channel/uri_parser_test.cc +++ b/test/core/client_channel/uri_parser_test.cc @@ -119,7 +119,7 @@ static void test_query_parts() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_succeeds("http://www.google.com", "http", "www.google.com", "", "", ""); test_succeeds("dns:///foo", "dns", "", "/foo", "", ""); diff --git a/test/core/compression/algorithm_test.cc b/test/core/compression/algorithm_test.cc index 8989a419897..24fe83774b8 100644 --- a/test/core/compression/algorithm_test.cc +++ b/test/core/compression/algorithm_test.cc @@ -105,7 +105,7 @@ static void test_algorithm_failure(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_algorithm_mesh(); diff --git a/test/core/compression/message_compress_test.cc b/test/core/compression/message_compress_test.cc index e3fe825fdf6..e2abf2d3215 100644 --- a/test/core/compression/message_compress_test.cc +++ b/test/core/compression/message_compress_test.cc @@ -292,7 +292,7 @@ int main(int argc, char** argv) { GRPC_SLICE_SPLIT_IDENTITY, GRPC_SLICE_SPLIT_ONE_BYTE}; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); for (i = 0; i < GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT; i++) { diff --git a/test/core/end2end/bad_server_response_test.cc b/test/core/end2end/bad_server_response_test.cc index f7396a16845..f8ffb551805 100644 --- a/test/core/end2end/bad_server_response_test.cc +++ b/test/core/end2end/bad_server_response_test.cc @@ -302,7 +302,7 @@ static void run_test(const char* response_payload, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); /* status defined in hpack static table */ diff --git a/test/core/end2end/connection_refused_test.cc b/test/core/end2end/connection_refused_test.cc index 33812ec8e5e..4318811b818 100644 --- a/test/core/end2end/connection_refused_test.cc +++ b/test/core/end2end/connection_refused_test.cc @@ -142,7 +142,7 @@ static void run_test(bool wait_for_ready, bool use_service_config) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_test(false /* wait_for_ready */, false /* use_service_config */); run_test(true /* wait_for_ready */, false /* use_service_config */); run_test(true /* wait_for_ready */, true /* use_service_config */); diff --git a/test/core/end2end/dualstack_socket_test.cc b/test/core/end2end/dualstack_socket_test.cc index eb1d043fb29..330af8fce07 100644 --- a/test/core/end2end/dualstack_socket_test.cc +++ b/test/core/end2end/dualstack_socket_test.cc @@ -303,7 +303,7 @@ int external_dns_works(const char* host) { int main(int argc, char** argv) { int do_ipv6 = 1; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); if (!grpc_ipv6_loopback_available()) { diff --git a/test/core/end2end/fixtures/h2_census.cc b/test/core/end2end/fixtures/h2_census.cc index 29b1d6d8839..60442ddcc77 100644 --- a/test/core/end2end/fixtures/h2_census.cc +++ b/test/core/end2end/fixtures/h2_census.cc @@ -118,7 +118,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_compress.cc b/test/core/end2end/fixtures/h2_compress.cc index 4aaadf715c0..04142daf63f 100644 --- a/test/core/end2end/fixtures/h2_compress.cc +++ b/test/core/end2end/fixtures/h2_compress.cc @@ -118,7 +118,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_fakesec.cc b/test/core/end2end/fixtures/h2_fakesec.cc index a653d7c477f..ad83aab39f4 100644 --- a/test/core/end2end/fixtures/h2_fakesec.cc +++ b/test/core/end2end/fixtures/h2_fakesec.cc @@ -142,7 +142,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_fd.cc b/test/core/end2end/fixtures/h2_fd.cc index 52be0f7fd51..5d06bd5f3be 100644 --- a/test/core/end2end/fixtures/h2_fd.cc +++ b/test/core/end2end/fixtures/h2_fd.cc @@ -104,7 +104,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_full+pipe.cc b/test/core/end2end/fixtures/h2_full+pipe.cc index c5329640dcd..6d559c4e516 100644 --- a/test/core/end2end/fixtures/h2_full+pipe.cc +++ b/test/core/end2end/fixtures/h2_full+pipe.cc @@ -105,7 +105,7 @@ int main(int argc, char** argv) { grpc_allow_specialized_wakeup_fd = 0; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_full+trace.cc b/test/core/end2end/fixtures/h2_full+trace.cc index ba7a7803049..2bbad487013 100644 --- a/test/core/end2end/fixtures/h2_full+trace.cc +++ b/test/core/end2end/fixtures/h2_full+trace.cc @@ -113,7 +113,7 @@ int main(int argc, char** argv) { g_fixture_slowdown_factor = 10; #endif - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_full+workarounds.cc b/test/core/end2end/fixtures/h2_full+workarounds.cc index 78da8418f6c..cb0f7d275b3 100644 --- a/test/core/end2end/fixtures/h2_full+workarounds.cc +++ b/test/core/end2end/fixtures/h2_full+workarounds.cc @@ -114,7 +114,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_full.cc b/test/core/end2end/fixtures/h2_full.cc index 0c826b68368..c0d21288c7e 100644 --- a/test/core/end2end/fixtures/h2_full.cc +++ b/test/core/end2end/fixtures/h2_full.cc @@ -97,7 +97,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_http_proxy.cc b/test/core/end2end/fixtures/h2_http_proxy.cc index 0af8a29a152..9b6a81494e1 100644 --- a/test/core/end2end/fixtures/h2_http_proxy.cc +++ b/test/core/end2end/fixtures/h2_http_proxy.cc @@ -120,7 +120,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_local.cc b/test/core/end2end/fixtures/h2_local.cc index cce8f1745a8..18d690ff222 100644 --- a/test/core/end2end/fixtures/h2_local.cc +++ b/test/core/end2end/fixtures/h2_local.cc @@ -140,7 +140,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_oauth2.cc b/test/core/end2end/fixtures/h2_oauth2.cc index 37397d6450a..113a6b11732 100644 --- a/test/core/end2end/fixtures/h2_oauth2.cc +++ b/test/core/end2end/fixtures/h2_oauth2.cc @@ -224,7 +224,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_proxy.cc b/test/core/end2end/fixtures/h2_proxy.cc index a32000061a3..e334396ea7c 100644 --- a/test/core/end2end/fixtures/h2_proxy.cc +++ b/test/core/end2end/fixtures/h2_proxy.cc @@ -124,7 +124,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.cc b/test/core/end2end/fixtures/h2_sockpair+trace.cc index eb71e24c772..4f393b22d05 100644 --- a/test/core/end2end/fixtures/h2_sockpair+trace.cc +++ b/test/core/end2end/fixtures/h2_sockpair+trace.cc @@ -140,7 +140,7 @@ int main(int argc, char** argv) { g_fixture_slowdown_factor = 10; #endif - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_sockpair.cc b/test/core/end2end/fixtures/h2_sockpair.cc index 904bda54586..1627fe0eb49 100644 --- a/test/core/end2end/fixtures/h2_sockpair.cc +++ b/test/core/end2end/fixtures/h2_sockpair.cc @@ -126,7 +126,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.cc b/test/core/end2end/fixtures/h2_sockpair_1byte.cc index 45f7f254ac5..8f1024b774d 100644 --- a/test/core/end2end/fixtures/h2_sockpair_1byte.cc +++ b/test/core/end2end/fixtures/h2_sockpair_1byte.cc @@ -140,7 +140,7 @@ int main(int argc, char** argv) { g_fixture_slowdown_factor = 2; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_ssl.cc b/test/core/end2end/fixtures/h2_ssl.cc index 4d6c8157164..1fcd785e251 100644 --- a/test/core/end2end/fixtures/h2_ssl.cc +++ b/test/core/end2end/fixtures/h2_ssl.cc @@ -158,7 +158,7 @@ int main(int argc, char** argv) { size_t roots_size = strlen(test_root_cert); char* roots_filename; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); /* Set the SSL roots env var. */ diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.cc b/test/core/end2end/fixtures/h2_ssl_proxy.cc index 09cbf974b61..f1858079426 100644 --- a/test/core/end2end/fixtures/h2_ssl_proxy.cc +++ b/test/core/end2end/fixtures/h2_ssl_proxy.cc @@ -199,7 +199,7 @@ int main(int argc, char** argv) { size_t roots_size = strlen(test_root_cert); char* roots_filename; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); /* Set the SSL roots env var. */ diff --git a/test/core/end2end/fixtures/h2_uds.cc b/test/core/end2end/fixtures/h2_uds.cc index 2c81c3d3622..f251bbd28c5 100644 --- a/test/core/end2end/fixtures/h2_uds.cc +++ b/test/core/end2end/fixtures/h2_uds.cc @@ -102,7 +102,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/inproc.cc b/test/core/end2end/fixtures/inproc.cc index be6eda84836..dadf3ef455d 100644 --- a/test/core/end2end/fixtures/inproc.cc +++ b/test/core/end2end/fixtures/inproc.cc @@ -83,7 +83,7 @@ static grpc_end2end_test_config configs[] = { int main(int argc, char** argv) { size_t i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc index e97a544e12c..9b6eddee6e1 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.cc +++ b/test/core/end2end/fuzzers/api_fuzzer.cc @@ -378,7 +378,7 @@ grpc_ares_request* my_dns_lookup_ares_locked( const char* dns_server, const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** lb_addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout, grpc_combiner* combiner) { addr_req* r = static_cast(gpr_malloc(sizeof(*r))); r->addr = gpr_strdup(addr); r->on_done = on_done; diff --git a/test/core/end2end/goaway_server_test.cc b/test/core/end2end/goaway_server_test.cc index 3f1c5596ad9..66e8ca51614 100644 --- a/test/core/end2end/goaway_server_test.cc +++ b/test/core/end2end/goaway_server_test.cc @@ -48,7 +48,7 @@ static grpc_ares_request* (*iomgr_dns_lookup_ares_locked)( const char* dns_server, const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addresses, bool check_grpclb, - char** service_config_json, grpc_combiner* combiner); + char** service_config_json, int query_timeout_ms, grpc_combiner* combiner); static void (*iomgr_cancel_ares_request_locked)(grpc_ares_request* request); @@ -104,11 +104,11 @@ static grpc_ares_request* my_dns_lookup_ares_locked( const char* dns_server, const char* addr, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** lb_addrs, bool check_grpclb, char** service_config_json, - grpc_combiner* combiner) { + int query_timeout_ms, grpc_combiner* combiner) { if (0 != strcmp(addr, "test")) { return iomgr_dns_lookup_ares_locked( dns_server, addr, default_port, interested_parties, on_done, lb_addrs, - check_grpclb, service_config_json, combiner); + check_grpclb, service_config_json, query_timeout_ms, combiner); } grpc_error* error = GRPC_ERROR_NONE; @@ -144,7 +144,7 @@ int main(int argc, char** argv) { grpc_op ops[6]; grpc_op* op; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); gpr_mu_init(&g_mu); grpc_init(); diff --git a/test/core/end2end/h2_ssl_cert_test.cc b/test/core/end2end/h2_ssl_cert_test.cc index 2c5ee3b156e..cb0800bf899 100644 --- a/test/core/end2end/h2_ssl_cert_test.cc +++ b/test/core/end2end/h2_ssl_cert_test.cc @@ -358,7 +358,7 @@ int main(int argc, char** argv) { size_t roots_size = strlen(test_root_cert); char* roots_filename; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* Set the SSL roots env var. */ roots_file = gpr_tmpfile("chttp2_simple_ssl_cert_fullstack_test", &roots_filename); diff --git a/test/core/end2end/h2_ssl_session_reuse_test.cc b/test/core/end2end/h2_ssl_session_reuse_test.cc index b2f398625ab..fbcdcc4b3f3 100644 --- a/test/core/end2end/h2_ssl_session_reuse_test.cc +++ b/test/core/end2end/h2_ssl_session_reuse_test.cc @@ -258,7 +258,7 @@ int main(int argc, char** argv) { size_t roots_size = strlen(test_root_cert); char* roots_filename; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* Set the SSL roots env var. */ roots_file = gpr_tmpfile("chttp2_ssl_session_reuse_test", &roots_filename); GPR_ASSERT(roots_filename != nullptr); diff --git a/test/core/end2end/inproc_callback_test.cc b/test/core/end2end/inproc_callback_test.cc index 310030046af..72ad992d54c 100644 --- a/test/core/end2end/inproc_callback_test.cc +++ b/test/core/end2end/inproc_callback_test.cc @@ -495,7 +495,7 @@ static grpc_end2end_test_config configs[] = { }; int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); simple_request_pre_init(); diff --git a/test/core/end2end/invalid_call_argument_test.cc b/test/core/end2end/invalid_call_argument_test.cc index 6cb2e3ee806..bd28d192984 100644 --- a/test/core/end2end/invalid_call_argument_test.cc +++ b/test/core/end2end/invalid_call_argument_test.cc @@ -609,7 +609,7 @@ static void test_invalid_initial_metadata_reserved_key() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_invalid_initial_metadata_reserved_key(); test_non_null_reserved_on_start_batch(); diff --git a/test/core/end2end/multiple_server_queues_test.cc b/test/core/end2end/multiple_server_queues_test.cc index dfa3b48b52d..5ae828c1e39 100644 --- a/test/core/end2end/multiple_server_queues_test.cc +++ b/test/core/end2end/multiple_server_queues_test.cc @@ -27,7 +27,7 @@ int main(int argc, char** argv) { grpc_server* server; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); attr.version = 1; diff --git a/test/core/end2end/no_server_test.cc b/test/core/end2end/no_server_test.cc index e8ce4032e0f..5dda748f5a5 100644 --- a/test/core/end2end/no_server_test.cc +++ b/test/core/end2end/no_server_test.cc @@ -107,7 +107,7 @@ void run_test(bool wait_for_ready) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_test(true /* wait_for_ready */); run_test(false /* wait_for_ready */); return 0; diff --git a/test/core/fling/client.cc b/test/core/fling/client.cc index 05dc3052d1b..2a7a5ca6232 100644 --- a/test/core/fling/client.cc +++ b/test/core/fling/client.cc @@ -158,11 +158,11 @@ int main(int argc, char** argv) { gpr_timers_set_log_filename("latency_trace.fling_client.txt"); - grpc_init(); - GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; - grpc_test_init(1, fake_argv); + grpc::testing::TestEnvironment env(1, fake_argv); + + grpc_init(); int warmup_seconds = 1; int benchmark_seconds = 5; diff --git a/test/core/gpr/BUILD b/test/core/gpr/BUILD index d58d4f2a14d..67657ee1ce9 100644 --- a/test/core/gpr/BUILD +++ b/test/core/gpr/BUILD @@ -81,12 +81,12 @@ grpc_cc_test( grpc_cc_test( name = "mpscq_test", srcs = ["mpscq_test.cc"], + exec_compatible_with = ["//third_party/toolchains/machine_size:large"], language = "C++", deps = [ "//:gpr", "//test/core/util:gpr_test_util", ], - data = ["//third_party/toolchains:RBE_USE_MACHINE_TYPE_LARGE"], ) grpc_cc_test( diff --git a/test/core/gpr/alloc_test.cc b/test/core/gpr/alloc_test.cc index 36cdc02ff22..0b110e2b77d 100644 --- a/test/core/gpr/alloc_test.cc +++ b/test/core/gpr/alloc_test.cc @@ -64,7 +64,7 @@ static void test_malloc_aligned() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_custom_allocs(); test_malloc_aligned(); return 0; diff --git a/test/core/gpr/arena_test.cc b/test/core/gpr/arena_test.cc index 3e7c9065915..de4bd9804eb 100644 --- a/test/core/gpr/arena_test.cc +++ b/test/core/gpr/arena_test.cc @@ -116,7 +116,7 @@ static void concurrent_test(void) { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_noop(); TEST(0_1, 0, 1); diff --git a/test/core/gpr/cpu_test.cc b/test/core/gpr/cpu_test.cc index 1052d40b421..dbaeb08c183 100644 --- a/test/core/gpr/cpu_test.cc +++ b/test/core/gpr/cpu_test.cc @@ -144,7 +144,7 @@ static void cpu_test(void) { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); cpu_test(); return 0; } diff --git a/test/core/gpr/env_test.cc b/test/core/gpr/env_test.cc index 3f4b4932394..a8206bd3cfd 100644 --- a/test/core/gpr/env_test.cc +++ b/test/core/gpr/env_test.cc @@ -43,7 +43,7 @@ static void test_setenv_getenv(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_setenv_getenv(); return 0; } diff --git a/test/core/gpr/host_port_test.cc b/test/core/gpr/host_port_test.cc index b5d88b2b011..b01bbf4b695 100644 --- a/test/core/gpr/host_port_test.cc +++ b/test/core/gpr/host_port_test.cc @@ -50,7 +50,7 @@ static void test_join_host_port_garbage(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_join_host_port(); test_join_host_port_garbage(); diff --git a/test/core/gpr/log_test.cc b/test/core/gpr/log_test.cc index 839ff0aef94..f96257738b2 100644 --- a/test/core/gpr/log_test.cc +++ b/test/core/gpr/log_test.cc @@ -53,7 +53,7 @@ static void test_should_not_log(gpr_log_func_args* args) { GPR_ASSERT(false); } gpr_log(SEVERITY, "hello %d %d %d", 1, 2, 3); int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* test logging at various verbosity levels */ gpr_log(GPR_DEBUG, "%s", "hello world"); gpr_log(GPR_INFO, "%s", "hello world"); diff --git a/test/core/gpr/mpscq_test.cc b/test/core/gpr/mpscq_test.cc index f51bdf8c502..c826ccb498b 100644 --- a/test/core/gpr/mpscq_test.cc +++ b/test/core/gpr/mpscq_test.cc @@ -182,7 +182,7 @@ static void test_mt_multipop(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_serial(); test_mt(); test_mt_multipop(); diff --git a/test/core/gpr/murmur_hash_test.cc b/test/core/gpr/murmur_hash_test.cc index 2d2fa72cfbc..fdc2cfa76b3 100644 --- a/test/core/gpr/murmur_hash_test.cc +++ b/test/core/gpr/murmur_hash_test.cc @@ -64,7 +64,7 @@ static void verification_test(hash_func hash, uint32_t expected) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* basic tests to verify that things don't crash */ gpr_murmur_hash3("", 0, 0); gpr_murmur_hash3("xyz", 3, 0); diff --git a/test/core/gpr/spinlock_test.cc b/test/core/gpr/spinlock_test.cc index 0ee72edb153..8bd9396da6e 100644 --- a/test/core/gpr/spinlock_test.cc +++ b/test/core/gpr/spinlock_test.cc @@ -149,7 +149,7 @@ static void inctry(void* v /*=m*/) { /* ------------------------------------------------- */ int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test("spinlock", &inc, 1, 1); test("spinlock try", &inctry, 1, 1); return 0; diff --git a/test/core/gpr/string_test.cc b/test/core/gpr/string_test.cc index 9f3b3124658..7da7b18778b 100644 --- a/test/core/gpr/string_test.cc +++ b/test/core/gpr/string_test.cc @@ -295,7 +295,7 @@ static void test_is_true(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_strdup(); test_dump(); test_parse_uint32(); diff --git a/test/core/gpr/sync_test.cc b/test/core/gpr/sync_test.cc index 24b4562819f..fc7216e3601 100644 --- a/test/core/gpr/sync_test.cc +++ b/test/core/gpr/sync_test.cc @@ -458,7 +458,7 @@ static void refcheck(void* v /*=m*/) { /* ------------------------------------------------- */ int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test("mutex", &inc, nullptr, 1, 1); test("mutex try", &inctry, nullptr, 1, 1); test("cv", &inc_by_turns, nullptr, 1, 1); diff --git a/test/core/gpr/time_test.cc b/test/core/gpr/time_test.cc index 6f070f58df1..a32cbfb09aa 100644 --- a/test/core/gpr/time_test.cc +++ b/test/core/gpr/time_test.cc @@ -254,7 +254,7 @@ static void test_cmp_extreme(void) { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_values(); test_add_sub(); diff --git a/test/core/gpr/tls_test.cc b/test/core/gpr/tls_test.cc index 0502fc7ef4d..d1bed0aafe3 100644 --- a/test/core/gpr/tls_test.cc +++ b/test/core/gpr/tls_test.cc @@ -50,7 +50,7 @@ static void thd_body(void* arg) { int main(int argc, char* argv[]) { grpc_core::Thread threads[NUM_THREADS]; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); gpr_tls_init(&test_var); diff --git a/test/core/gpr/useful_test.cc b/test/core/gpr/useful_test.cc index 619c800c4d9..4f8582ab415 100644 --- a/test/core/gpr/useful_test.cc +++ b/test/core/gpr/useful_test.cc @@ -26,7 +26,7 @@ int main(int argc, char** argv) { int four[4]; int five[5]; uint32_t bitset = 0; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); GPR_ASSERT(GPR_MIN(1, 2) == 1); GPR_ASSERT(GPR_MAX(1, 2) == 2); diff --git a/test/core/gprpp/fork_test.cc b/test/core/gprpp/fork_test.cc index 642f910489c..0f56eead49d 100644 --- a/test/core/gprpp/fork_test.cc +++ b/test/core/gprpp/fork_test.cc @@ -130,7 +130,7 @@ static void test_exec_count() { } int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_init(); test_thd_count(); test_exec_count(); diff --git a/test/core/gprpp/inlined_vector_test.cc b/test/core/gprpp/inlined_vector_test.cc index 73e0773b31d..f943128f53c 100644 --- a/test/core/gprpp/inlined_vector_test.cc +++ b/test/core/gprpp/inlined_vector_test.cc @@ -116,7 +116,7 @@ typedef InlinedVector IntVec8; const size_t kInlinedFillSize = kInlinedLength - 1; const size_t kAllocatedFillSize = kInlinedLength + 1; -TEST(InlinedVectorTest, CopyConstructerInlined) { +TEST(InlinedVectorTest, CopyConstructorInlined) { IntVec8 original; FillVector(&original, kInlinedFillSize); IntVec8 copy_constructed(original); @@ -125,7 +125,7 @@ TEST(InlinedVectorTest, CopyConstructerInlined) { } } -TEST(InlinedVectorTest, CopyConstructerAllocated) { +TEST(InlinedVectorTest, CopyConstructorAllocated) { IntVec8 original; FillVector(&original, kAllocatedFillSize); IntVec8 copy_constructed(original); @@ -264,6 +264,166 @@ TEST(InlinedVectorTest, MoveAssignmentAllocatedAllocated) { EXPECT_EQ(move_assigned.data(), old_data); } +// A copyable and movable value class, used to test that elements' copy +// and move methods are called correctly. +class Value { + public: + explicit Value(int v) : value_(MakeUnique(v)) {} + + // copyable + Value(const Value& v) { + value_ = MakeUnique(*v.value_); + copied_ = true; + } + Value& operator=(const Value& v) { + value_ = MakeUnique(*v.value_); + copied_ = true; + return *this; + } + + // movable + Value(Value&& v) { + value_ = std::move(v.value_); + moved_ = true; + } + Value& operator=(Value&& v) { + value_ = std::move(v.value_); + moved_ = true; + return *this; + } + + const UniquePtr& value() const { return value_; } + bool copied() const { return copied_; } + bool moved() const { return moved_; } + + private: + UniquePtr value_; + bool copied_ = false; + bool moved_ = false; +}; + +TEST(InlinedVectorTest, CopyConstructorCopiesElementsInlined) { + InlinedVector v1; + v1.emplace_back(3); + InlinedVector v2(v1); + EXPECT_EQ(v2.size(), 1UL); + EXPECT_EQ(*v2[0].value(), 3); + // Addresses should differ. + EXPECT_NE(v1[0].value().get(), v2[0].value().get()); + EXPECT_TRUE(v2[0].copied()); +} + +TEST(InlinedVectorTest, CopyConstructorCopiesElementsAllocated) { + InlinedVector v1; + v1.reserve(2); + v1.emplace_back(3); + v1.emplace_back(5); + InlinedVector v2(v1); + EXPECT_EQ(v2.size(), 2UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(*v2[1].value(), 5); + // Addresses should differ. + EXPECT_NE(v1[0].value().get(), v2[0].value().get()); + EXPECT_NE(v1[1].value().get(), v2[1].value().get()); + EXPECT_TRUE(v2[0].copied()); + EXPECT_TRUE(v2[1].copied()); +} + +TEST(InlinedVectorTest, CopyAssignmentCopiesElementsInlined) { + InlinedVector v1; + v1.emplace_back(3); + InlinedVector v2; + EXPECT_EQ(v2.size(), 0UL); + v2 = v1; + EXPECT_EQ(v2.size(), 1UL); + EXPECT_EQ(*v2[0].value(), 3); + // Addresses should differ. + EXPECT_NE(v1[0].value().get(), v2[0].value().get()); + EXPECT_TRUE(v2[0].copied()); +} + +TEST(InlinedVectorTest, CopyAssignmentCopiesElementsAllocated) { + InlinedVector v1; + v1.reserve(2); + v1.emplace_back(3); + v1.emplace_back(5); + InlinedVector v2; + EXPECT_EQ(v2.size(), 0UL); + v2 = v1; + EXPECT_EQ(v2.size(), 2UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(*v2[1].value(), 5); + // Addresses should differ. + EXPECT_NE(v1[0].value().get(), v2[0].value().get()); + EXPECT_NE(v1[1].value().get(), v2[1].value().get()); + EXPECT_TRUE(v2[0].copied()); + EXPECT_TRUE(v2[1].copied()); +} + +TEST(InlinedVectorTest, MoveConstructorMovesElementsInlined) { + InlinedVector v1; + v1.emplace_back(3); + int* addr = v1[0].value().get(); + InlinedVector v2(std::move(v1)); + EXPECT_EQ(v2.size(), 1UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(addr, v2[0].value().get()); + EXPECT_TRUE(v2[0].moved()); +} + +TEST(InlinedVectorTest, MoveConstructorMovesElementsAllocated) { + InlinedVector v1; + v1.reserve(2); + v1.emplace_back(3); + v1.emplace_back(5); + int* addr1 = v1[0].value().get(); + int* addr2 = v1[1].value().get(); + Value* data1 = v1.data(); + InlinedVector v2(std::move(v1)); + EXPECT_EQ(v2.size(), 2UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(*v2[1].value(), 5); + EXPECT_EQ(addr1, v2[0].value().get()); + EXPECT_EQ(addr2, v2[1].value().get()); + // In this case, elements won't be moved, because we have just stolen + // the underlying storage. + EXPECT_EQ(data1, v2.data()); +} + +TEST(InlinedVectorTest, MoveAssignmentMovesElementsInlined) { + InlinedVector v1; + v1.emplace_back(3); + int* addr = v1[0].value().get(); + InlinedVector v2; + EXPECT_EQ(v2.size(), 0UL); + v2 = std::move(v1); + EXPECT_EQ(v2.size(), 1UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(addr, v2[0].value().get()); + EXPECT_TRUE(v2[0].moved()); +} + +TEST(InlinedVectorTest, MoveAssignmentMovesElementsAllocated) { + InlinedVector v1; + v1.reserve(2); + v1.emplace_back(3); + v1.emplace_back(5); + int* addr1 = v1[0].value().get(); + int* addr2 = v1[1].value().get(); + Value* data1 = v1.data(); + InlinedVector v2; + EXPECT_EQ(v2.size(), 0UL); + v2 = std::move(v1); + EXPECT_EQ(v2.size(), 2UL); + EXPECT_EQ(*v2[0].value(), 3); + EXPECT_EQ(*v2[1].value(), 5); + EXPECT_EQ(addr1, v2[0].value().get()); + EXPECT_EQ(addr2, v2[1].value().get()); + // In this case, elements won't be moved, because we have just stolen + // the underlying storage. + EXPECT_EQ(data1, v2.data()); +} + TEST(InlinedVectorTest, PopBackInlined) { InlinedVector, 2> v; // Add two elements, pop one out @@ -294,7 +454,7 @@ TEST(InlinedVectorTest, PopBackAllocated) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/manual_constructor_test.cc b/test/core/gprpp/manual_constructor_test.cc index af162ae8e8a..a5a45133d86 100644 --- a/test/core/gprpp/manual_constructor_test.cc +++ b/test/core/gprpp/manual_constructor_test.cc @@ -92,7 +92,7 @@ static void complex_test() { /* ------------------------------------------------- */ int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); basic_test(); complex_test(); return 0; diff --git a/test/core/gprpp/memory_test.cc b/test/core/gprpp/memory_test.cc index 180c36fad7f..bb6a219a848 100644 --- a/test/core/gprpp/memory_test.cc +++ b/test/core/gprpp/memory_test.cc @@ -68,7 +68,7 @@ TEST(MemoryTest, UniquePtrWithCustomDeleter) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/orphanable_test.cc b/test/core/gprpp/orphanable_test.cc index ad6b9ac8674..546f395cef6 100644 --- a/test/core/gprpp/orphanable_test.cc +++ b/test/core/gprpp/orphanable_test.cc @@ -114,7 +114,7 @@ TEST(OrphanablePtr, InternallyRefCountedWithTracing) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/ref_counted_ptr_test.cc b/test/core/gprpp/ref_counted_ptr_test.cc index 463b5e89667..512687eb679 100644 --- a/test/core/gprpp/ref_counted_ptr_test.cc +++ b/test/core/gprpp/ref_counted_ptr_test.cc @@ -241,7 +241,7 @@ TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingSubclass) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/ref_counted_test.cc b/test/core/gprpp/ref_counted_test.cc index 62a3ea4d53e..5aba1634efb 100644 --- a/test/core/gprpp/ref_counted_test.cc +++ b/test/core/gprpp/ref_counted_test.cc @@ -116,7 +116,7 @@ TEST(RefCountedNonPolymorphicWithTracing, Basic) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/gprpp/thd_test.cc b/test/core/gprpp/thd_test.cc index 82dd681049b..06aa58984b0 100644 --- a/test/core/gprpp/thd_test.cc +++ b/test/core/gprpp/thd_test.cc @@ -92,7 +92,7 @@ static void test2(void) { /* ------------------------------------------------- */ int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test1(); test2(); return 0; diff --git a/test/core/http/format_request_test.cc b/test/core/http/format_request_test.cc index 353e138b2a1..b0a90c4613b 100644 --- a/test/core/http/format_request_test.cc +++ b/test/core/http/format_request_test.cc @@ -138,7 +138,7 @@ static void test_format_post_request_content_type_override(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_format_get_request(); diff --git a/test/core/http/httpcli_test.cc b/test/core/http/httpcli_test.cc index a51a0a5f6d7..bfd75f86491 100644 --- a/test/core/http/httpcli_test.cc +++ b/test/core/http/httpcli_test.cc @@ -145,7 +145,7 @@ static void destroy_pops(void* p, grpc_error* error) { int main(int argc, char** argv) { gpr_subprocess* server; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_closure destroyed; diff --git a/test/core/http/httpscli_test.cc b/test/core/http/httpscli_test.cc index 3fecf2b08bb..326b0e95e25 100644 --- a/test/core/http/httpscli_test.cc +++ b/test/core/http/httpscli_test.cc @@ -201,7 +201,7 @@ int main(int argc, char** argv) { gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(5, GPR_TIMESPAN))); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); grpc_httpcli_context_init(&g_context); grpc_pollset* pollset = diff --git a/test/core/http/parser_test.cc b/test/core/http/parser_test.cc index fe824f57fce..d105b40bcd6 100644 --- a/test/core/http/parser_test.cc +++ b/test/core/http/parser_test.cc @@ -218,7 +218,7 @@ int main(int argc, char** argv) { GRPC_SLICE_SPLIT_ONE_BYTE}; char *tmp1, *tmp2; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); for (i = 0; i < GPR_ARRAY_SIZE(split_modes); i++) { diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 70ee83acd23..e278632e502 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -40,7 +40,7 @@ grpc_cc_library( grpc_cc_test( name = "combiner_test", srcs = ["combiner_test.cc"], - data = ["//third_party/toolchains:RBE_USE_MACHINE_TYPE_LARGE"], + exec_compatible_with = ["//third_party/toolchains/machine_size:large"], language = "C++", deps = [ "//:gpr", diff --git a/test/core/iomgr/buffer_list_test.cc b/test/core/iomgr/buffer_list_test.cc index e104e8e91a0..eca8f76e673 100644 --- a/test/core/iomgr/buffer_list_test.cc +++ b/test/core/iomgr/buffer_list_test.cc @@ -97,7 +97,7 @@ static void TestTcpBufferList() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); TestTcpBufferList(); grpc_shutdown(); diff --git a/test/core/iomgr/combiner_test.cc b/test/core/iomgr/combiner_test.cc index cf2c7db8462..c39c3fc8fce 100644 --- a/test/core/iomgr/combiner_test.cc +++ b/test/core/iomgr/combiner_test.cc @@ -144,7 +144,7 @@ static void test_execute_finally(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_no_op(); test_execute_one(); diff --git a/test/core/iomgr/endpoint_pair_test.cc b/test/core/iomgr/endpoint_pair_test.cc index ad38076b516..3ddbe7f2fc0 100644 --- a/test/core/iomgr/endpoint_pair_test.cc +++ b/test/core/iomgr/endpoint_pair_test.cc @@ -60,7 +60,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/error_test.cc b/test/core/iomgr/error_test.cc index d78a8c2af39..3ba90147aad 100644 --- a/test/core/iomgr/error_test.cc +++ b/test/core/iomgr/error_test.cc @@ -215,7 +215,7 @@ static void test_overflow() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_set_get_int(); test_set_get_str(); diff --git a/test/core/iomgr/ev_epollex_linux_test.cc b/test/core/iomgr/ev_epollex_linux_test.cc index 08d1e68b398..faa3ef344a1 100644 --- a/test/core/iomgr/ev_epollex_linux_test.cc +++ b/test/core/iomgr/ev_epollex_linux_test.cc @@ -92,7 +92,7 @@ static void test_pollable_owner_fd() { int main(int argc, char** argv) { const char* poll_strategy = nullptr; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/fd_conservation_posix_test.cc b/test/core/iomgr/fd_conservation_posix_test.cc index 4866e350d53..0d27b94dc2d 100644 --- a/test/core/iomgr/fd_conservation_posix_test.cc +++ b/test/core/iomgr/fd_conservation_posix_test.cc @@ -29,7 +29,7 @@ int main(int argc, char** argv) { struct rlimit rlim; grpc_endpoint_pair p; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/fd_posix_test.cc b/test/core/iomgr/fd_posix_test.cc index 4ea2389bbd8..cf5ffc63543 100644 --- a/test/core/iomgr/fd_posix_test.cc +++ b/test/core/iomgr/fd_posix_test.cc @@ -515,7 +515,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/grpc_ipv6_loopback_available_test.cc b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc index 329aa9a8517..2ef1f1978d6 100644 --- a/test/core/iomgr/grpc_ipv6_loopback_available_test.cc +++ b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc @@ -32,7 +32,7 @@ #endif int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); // This test assumes that the ipv6 loopback is available // in all environments in which grpc tests run in. diff --git a/test/core/iomgr/load_file_test.cc b/test/core/iomgr/load_file_test.cc index 38c8710535b..a0e0e4d7a74 100644 --- a/test/core/iomgr/load_file_test.cc +++ b/test/core/iomgr/load_file_test.cc @@ -152,7 +152,7 @@ static void test_load_big_file(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_load_empty_file(); test_load_failure(); diff --git a/test/core/iomgr/resolve_address_posix_test.cc b/test/core/iomgr/resolve_address_posix_test.cc index e495e4c8770..ceeb70a1086 100644 --- a/test/core/iomgr/resolve_address_posix_test.cc +++ b/test/core/iomgr/resolve_address_posix_test.cc @@ -158,7 +158,7 @@ static void test_unix_socket_path_name_too_long(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { diff --git a/test/core/iomgr/resolve_address_test.cc b/test/core/iomgr/resolve_address_test.cc index 8d69bab5b12..1d9e1ee27e2 100644 --- a/test/core/iomgr/resolve_address_test.cc +++ b/test/core/iomgr/resolve_address_test.cc @@ -271,7 +271,7 @@ int main(int argc, char** argv) { abort(); } // Run the test. - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/resource_quota_test.cc b/test/core/iomgr/resource_quota_test.cc index f3b35fed327..4cbc016d587 100644 --- a/test/core/iomgr/resource_quota_test.cc +++ b/test/core/iomgr/resource_quota_test.cc @@ -891,7 +891,7 @@ static void test_thread_maxquota_change() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); gpr_mu_init(&g_mu); gpr_cv_init(&g_cv); diff --git a/test/core/iomgr/sockaddr_utils_test.cc b/test/core/iomgr/sockaddr_utils_test.cc index 3783f968b7d..250d36a74a6 100644 --- a/test/core/iomgr/sockaddr_utils_test.cc +++ b/test/core/iomgr/sockaddr_utils_test.cc @@ -270,7 +270,7 @@ static void test_sockaddr_set_get_port(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_sockaddr_is_v4mapped(); test_sockaddr_to_v4mapped(); diff --git a/test/core/iomgr/socket_utils_test.cc b/test/core/iomgr/socket_utils_test.cc index a21f3fac62e..420873734de 100644 --- a/test/core/iomgr/socket_utils_test.cc +++ b/test/core/iomgr/socket_utils_test.cc @@ -80,7 +80,7 @@ static const grpc_socket_mutator_vtable mutator_vtable = { int main(int argc, char** argv) { int sock; grpc_error* err; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); sock = socket(PF_INET, SOCK_STREAM, 0); GPR_ASSERT(sock > 0); diff --git a/test/core/iomgr/tcp_client_posix_test.cc b/test/core/iomgr/tcp_client_posix_test.cc index 90fc5aecfc6..5cf3530c77a 100644 --- a/test/core/iomgr/tcp_client_posix_test.cc +++ b/test/core/iomgr/tcp_client_posix_test.cc @@ -191,7 +191,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { diff --git a/test/core/iomgr/tcp_client_uv_test.cc b/test/core/iomgr/tcp_client_uv_test.cc index 27f894e3f3c..bde8c2f3539 100644 --- a/test/core/iomgr/tcp_client_uv_test.cc +++ b/test/core/iomgr/tcp_client_uv_test.cc @@ -188,7 +188,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/tcp_posix_test.cc b/test/core/iomgr/tcp_posix_test.cc index 6447cc234db..80f17a914fa 100644 --- a/test/core/iomgr/tcp_posix_test.cc +++ b/test/core/iomgr/tcp_posix_test.cc @@ -623,7 +623,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); grpc_core::grpc_tcp_set_write_timestamps_callback(timestamps_verifier); { diff --git a/test/core/iomgr/tcp_server_posix_test.cc b/test/core/iomgr/tcp_server_posix_test.cc index d646df1daef..2c66cdec77f 100644 --- a/test/core/iomgr/tcp_server_posix_test.cc +++ b/test/core/iomgr/tcp_server_posix_test.cc @@ -437,7 +437,7 @@ int main(int argc, char** argv) { // Zalloc dst_addrs to avoid oversized frames. test_addrs* dst_addrs = static_cast(gpr_zalloc(sizeof(*dst_addrs))); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/tcp_server_uv_test.cc b/test/core/iomgr/tcp_server_uv_test.cc index e99fa79bfd8..625a18c0cc7 100644 --- a/test/core/iomgr/tcp_server_uv_test.cc +++ b/test/core/iomgr/tcp_server_uv_test.cc @@ -288,7 +288,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/iomgr/time_averaged_stats_test.cc b/test/core/iomgr/time_averaged_stats_test.cc index b932e62d1f6..2923a35d1b6 100644 --- a/test/core/iomgr/time_averaged_stats_test.cc +++ b/test/core/iomgr/time_averaged_stats_test.cc @@ -180,7 +180,7 @@ static void some_regress_some_persist_test(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); no_regress_no_persist_test_1(); no_regress_no_persist_test_2(); no_regress_no_persist_test_3(); diff --git a/test/core/iomgr/timer_heap_test.cc b/test/core/iomgr/timer_heap_test.cc index ebe5e6610d1..872cf17486f 100644 --- a/test/core/iomgr/timer_heap_test.cc +++ b/test/core/iomgr/timer_heap_test.cc @@ -286,7 +286,7 @@ static void shrink_test(void) { int main(int argc, char** argv) { int i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); for (i = 0; i < 5; i++) { test1(); diff --git a/test/core/iomgr/timer_list_test.cc b/test/core/iomgr/timer_list_test.cc index fd65d1abf1f..fa2444948b6 100644 --- a/test/core/iomgr/timer_list_test.cc +++ b/test/core/iomgr/timer_list_test.cc @@ -221,7 +221,7 @@ void long_running_service_cleanup_test(void) { int main(int argc, char** argv) { /* Tests with default g_start_time */ { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_core::ExecCtx::GlobalInit(); grpc_core::ExecCtx exec_ctx; grpc_determine_iomgr_platform(); @@ -235,7 +235,7 @@ int main(int argc, char** argv) { /* Begin long running service tests */ { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); /* Set g_start_time back 25 days. */ /* We set g_start_time here in case there are any initialization dependencies that use g_start_time. */ diff --git a/test/core/iomgr/udp_server_test.cc b/test/core/iomgr/udp_server_test.cc index d167c0131f3..f65783a0174 100644 --- a/test/core/iomgr/udp_server_test.cc +++ b/test/core/iomgr/udp_server_test.cc @@ -360,7 +360,7 @@ static void test_receive(int number_of_clients) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); if (grpc_is_socket_reuse_port_supported()) { g_num_listeners = 10; diff --git a/test/core/json/json_rewrite_test.cc b/test/core/json/json_rewrite_test.cc index 2fade12e13f..b7e89cdb1a3 100644 --- a/test/core/json/json_rewrite_test.cc +++ b/test/core/json/json_rewrite_test.cc @@ -287,7 +287,7 @@ void test_rewrites() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_rewrites(); gpr_log(GPR_INFO, "json_rewrite_test success"); return 0; diff --git a/test/core/json/json_stream_error_test.cc b/test/core/json/json_stream_error_test.cc index 00288d6d5ea..53e20be2069 100644 --- a/test/core/json/json_stream_error_test.cc +++ b/test/core/json/json_stream_error_test.cc @@ -49,7 +49,7 @@ static void read_error() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); read_error(); gpr_log(GPR_INFO, "json_stream_error success"); return 0; diff --git a/test/core/json/json_test.cc b/test/core/json/json_test.cc index 7f1dbb774a6..03dd96a8ae1 100644 --- a/test/core/json/json_test.cc +++ b/test/core/json/json_test.cc @@ -184,7 +184,7 @@ static void test_atypical() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_pairs(); test_atypical(); gpr_log(GPR_INFO, "json_test success"); diff --git a/test/core/memory_usage/client.cc b/test/core/memory_usage/client.cc index 3c3fa53b515..467586ea5f4 100644 --- a/test/core/memory_usage/client.cc +++ b/test/core/memory_usage/client.cc @@ -193,11 +193,11 @@ int main(int argc, char** argv) { gpr_cmdline* cl; grpc_event event; - grpc_init(); - GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; - grpc_test_init(1, fake_argv); + grpc::testing::TestEnvironment env(1, fake_argv); + + grpc_init(); int warmup_iterations = 100; int benchmark_iterations = 1000; diff --git a/test/core/memory_usage/server.cc b/test/core/memory_usage/server.cc index 6f8a9bc0d46..7424797e6f5 100644 --- a/test/core/memory_usage/server.cc +++ b/test/core/memory_usage/server.cc @@ -162,7 +162,7 @@ int main(int argc, char** argv) { GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; - grpc_test_init(1, fake_argv); + grpc::testing::TestEnvironment env(1, fake_argv); grpc_init(); srand(static_cast(clock())); diff --git a/test/core/security/auth_context_test.cc b/test/core/security/auth_context_test.cc index 58f0d8e1c27..9a39afb8006 100644 --- a/test/core/security/auth_context_test.cc +++ b/test/core/security/auth_context_test.cc @@ -130,7 +130,7 @@ static void test_chained_context(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_empty_context(); test_simple_context(); test_chained_context(); diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc index 56c4c9c0ae1..b3e3c3c7415 100644 --- a/test/core/security/credentials_test.cc +++ b/test/core/security/credentials_test.cc @@ -1206,7 +1206,7 @@ static void test_auth_metadata_context(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_empty_md_array(); test_add_to_empty_md_array(); diff --git a/test/core/security/json_token_test.cc b/test/core/security/json_token_test.cc index 7a5b3355fec..a3ae18e6abd 100644 --- a/test/core/security/json_token_test.cc +++ b/test/core/security/json_token_test.cc @@ -482,7 +482,7 @@ static void test_parse_refresh_token_failure_no_refresh_token(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_parse_json_key_success(); test_parse_json_key_failure_bad_json(); diff --git a/test/core/security/jwt_verifier_test.cc b/test/core/security/jwt_verifier_test.cc index 9718580a08d..70155cdd065 100644 --- a/test/core/security/jwt_verifier_test.cc +++ b/test/core/security/jwt_verifier_test.cc @@ -600,7 +600,7 @@ static void test_jwt_verifier_bad_format(void) { /* bad key */ int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_jwt_issuer_email_domain(); test_claims_success(); diff --git a/test/core/security/linux_system_roots_test.cc b/test/core/security/linux_system_roots_test.cc index 24d446de359..cd8bd3beb77 100644 --- a/test/core/security/linux_system_roots_test.cc +++ b/test/core/security/linux_system_roots_test.cc @@ -86,7 +86,7 @@ TEST(CreateRootCertsBundleTest, BundlesCorrectly) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/security/secure_endpoint_test.cc b/test/core/security/secure_endpoint_test.cc index 23cef99dfa8..f6d02895b5f 100644 --- a/test/core/security/secure_endpoint_test.cc +++ b/test/core/security/secure_endpoint_test.cc @@ -208,7 +208,7 @@ static void destroy_pollset(void* p, grpc_error* error) { int main(int argc, char** argv) { grpc_closure destroyed; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc index fef0ea71f7d..e82a8627d40 100644 --- a/test/core/security/security_connector_test.cc +++ b/test/core/security/security_connector_test.cc @@ -430,7 +430,7 @@ static void test_default_ssl_roots(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_unauthenticated_ssl_peer(); diff --git a/test/core/security/ssl_credentials_test.cc b/test/core/security/ssl_credentials_test.cc index 9edcf42d3a4..7c9f5616654 100644 --- a/test/core/security/ssl_credentials_test.cc +++ b/test/core/security/ssl_credentials_test.cc @@ -56,7 +56,7 @@ static void test_convert_grpc_to_tsi_cert_pairs() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_convert_grpc_to_tsi_cert_pairs(); diff --git a/test/core/slice/b64_test.cc b/test/core/slice/b64_test.cc index 6b29443ba10..6677150c231 100644 --- a/test/core/slice/b64_test.cc +++ b/test/core/slice/b64_test.cc @@ -201,7 +201,7 @@ static void test_unpadded_decode(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_simple_encode_decode_b64_no_multiline(); test_simple_encode_decode_b64_multiline(); diff --git a/test/core/slice/percent_encoding_test.cc b/test/core/slice/percent_encoding_test.cc index e8d04fcc83c..ae6c39eb266 100644 --- a/test/core/slice/percent_encoding_test.cc +++ b/test/core/slice/percent_encoding_test.cc @@ -118,7 +118,7 @@ static void test_nonconformant_vector(const char* encoded, } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); TEST_VECTOR( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~", diff --git a/test/core/slice/slice_buffer_test.cc b/test/core/slice/slice_buffer_test.cc index e59986730b8..b53e3312df1 100644 --- a/test/core/slice/slice_buffer_test.cc +++ b/test/core/slice/slice_buffer_test.cc @@ -106,7 +106,7 @@ void test_slice_buffer_move_first() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_slice_buffer_add(); diff --git a/test/core/slice/slice_hash_table_test.cc b/test/core/slice/slice_hash_table_test.cc index 43ddfe9bf2c..08cfe91e5a1 100644 --- a/test/core/slice/slice_hash_table_test.cc +++ b/test/core/slice/slice_hash_table_test.cc @@ -217,7 +217,7 @@ TEST(SliceHashTable, CmpEmptyKeysDifferentValue) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_core::ExecCtx::GlobalInit(); int result = RUN_ALL_TESTS(); grpc_core::ExecCtx::GlobalShutdown(); diff --git a/test/core/slice/slice_string_helpers_test.cc b/test/core/slice/slice_string_helpers_test.cc index 860a1bfe034..1bbc0947bc6 100644 --- a/test/core/slice/slice_string_helpers_test.cc +++ b/test/core/slice/slice_string_helpers_test.cc @@ -195,7 +195,7 @@ static void test_strsplit_nospace(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_dump_slice(); test_strsplit(); test_strsplit_nospace(); diff --git a/test/core/slice/slice_test.cc b/test/core/slice/slice_test.cc index e683c41f312..1e53a1951c4 100644 --- a/test/core/slice/slice_test.cc +++ b/test/core/slice/slice_test.cc @@ -294,7 +294,7 @@ static void test_static_slice_copy_interning(void) { int main(int argc, char** argv) { unsigned length; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_slice_malloc_returns_something_sensible(); test_slice_new_returns_something_sensible(); diff --git a/test/core/slice/slice_weak_hash_table_test.cc b/test/core/slice/slice_weak_hash_table_test.cc index b0a243d572e..ab0a648727d 100644 --- a/test/core/slice/slice_weak_hash_table_test.cc +++ b/test/core/slice/slice_weak_hash_table_test.cc @@ -98,7 +98,7 @@ TEST(SliceWeakHashTable, ForceOverload) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_core::ExecCtx::GlobalInit(); int result = RUN_ALL_TESTS(); grpc_core::ExecCtx::GlobalShutdown(); diff --git a/test/core/surface/byte_buffer_reader_test.cc b/test/core/surface/byte_buffer_reader_test.cc index cff05caec14..301a1e283ba 100644 --- a/test/core/surface/byte_buffer_reader_test.cc +++ b/test/core/surface/byte_buffer_reader_test.cc @@ -267,7 +267,7 @@ static void test_byte_buffer_copy(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_read_one_slice(); test_read_one_slice_malloc(); test_read_none_compressed_slice(); diff --git a/test/core/surface/channel_create_test.cc b/test/core/surface/channel_create_test.cc index 56f4f602e87..5f109c0f840 100644 --- a/test/core/surface/channel_create_test.cc +++ b/test/core/surface/channel_create_test.cc @@ -44,7 +44,7 @@ void test_unknown_scheme_target(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_unknown_scheme_target(); grpc_shutdown(); diff --git a/test/core/surface/completion_queue_test.cc b/test/core/surface/completion_queue_test.cc index f7ce8a7042e..a157d75edab 100644 --- a/test/core/surface/completion_queue_test.cc +++ b/test/core/surface/completion_queue_test.cc @@ -440,7 +440,7 @@ struct thread_state { }; int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_no_op(); test_pollset_conversion(); diff --git a/test/core/surface/completion_queue_threading_test.cc b/test/core/surface/completion_queue_threading_test.cc index 0b82803af6f..4215aad14af 100644 --- a/test/core/surface/completion_queue_threading_test.cc +++ b/test/core/surface/completion_queue_threading_test.cc @@ -288,7 +288,7 @@ static void test_threading(size_t producers, size_t consumers) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_too_many_plucks(); test_threading(1, 1); diff --git a/test/core/surface/concurrent_connectivity_test.cc b/test/core/surface/concurrent_connectivity_test.cc index fbc5ec4c541..f606e89ac8d 100644 --- a/test/core/surface/concurrent_connectivity_test.cc +++ b/test/core/surface/concurrent_connectivity_test.cc @@ -300,7 +300,7 @@ int run_concurrent_watches_with_short_timeouts_test() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_concurrent_connectivity_test(); run_concurrent_watches_with_short_timeouts_test(); diff --git a/test/core/surface/init_test.cc b/test/core/surface/init_test.cc index 5749bc8b36d..1bcd13a0b89 100644 --- a/test/core/surface/init_test.cc +++ b/test/core/surface/init_test.cc @@ -60,7 +60,7 @@ static void test_repeatedly() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test(1); test(2); test(3); diff --git a/test/core/surface/lame_client_test.cc b/test/core/surface/lame_client_test.cc index fac5ca8f7f6..09c3d431977 100644 --- a/test/core/surface/lame_client_test.cc +++ b/test/core/surface/lame_client_test.cc @@ -75,7 +75,7 @@ int main(int argc, char** argv) { grpc_slice details; char* peer; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); grpc_metadata_array_init(&initial_metadata_recv); diff --git a/test/core/surface/num_external_connectivity_watchers_test.cc b/test/core/surface/num_external_connectivity_watchers_test.cc index 7b7a0b6dfc0..454cbd5747e 100644 --- a/test/core/surface/num_external_connectivity_watchers_test.cc +++ b/test/core/surface/num_external_connectivity_watchers_test.cc @@ -191,7 +191,7 @@ static const test_fixture secure_test = { }; int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_timeouts_test(&insecure_test); run_timeouts_test(&secure_test); diff --git a/test/core/surface/secure_channel_create_test.cc b/test/core/surface/secure_channel_create_test.cc index 06962179a23..5610d1ec4ab 100644 --- a/test/core/surface/secure_channel_create_test.cc +++ b/test/core/surface/secure_channel_create_test.cc @@ -70,7 +70,7 @@ void test_null_creds(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_security_connector_already_in_arg(); test_null_creds(); diff --git a/test/core/surface/sequential_connectivity_test.cc b/test/core/surface/sequential_connectivity_test.cc index 10562b3be9c..3f9a7baf98b 100644 --- a/test/core/surface/sequential_connectivity_test.cc +++ b/test/core/surface/sequential_connectivity_test.cc @@ -168,7 +168,7 @@ static const test_fixture secure_test = { }; int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); run_test(&insecure_test); run_test(&secure_test); diff --git a/test/core/surface/server_chttp2_test.cc b/test/core/surface/server_chttp2_test.cc index fd8ab9cd3d5..ffb7f14f987 100644 --- a/test/core/surface/server_chttp2_test.cc +++ b/test/core/surface/server_chttp2_test.cc @@ -67,7 +67,7 @@ void test_add_same_port_twice() { #endif int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_unparsable_target(); #ifndef GRPC_UV diff --git a/test/core/surface/server_test.cc b/test/core/surface/server_test.cc index b4eabd8d4d8..2fc166546b0 100644 --- a/test/core/surface/server_test.cc +++ b/test/core/surface/server_test.cc @@ -148,7 +148,7 @@ static void test_bind_server_to_addrs(const char** addrs, size_t n) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_register_method_fail(); test_request_call_on_no_server_cq(); diff --git a/test/core/transport/bdp_estimator_test.cc b/test/core/transport/bdp_estimator_test.cc index c7e6b2bd841..a795daaead7 100644 --- a/test/core/transport/bdp_estimator_test.cc +++ b/test/core/transport/bdp_estimator_test.cc @@ -139,7 +139,7 @@ INSTANTIATE_TEST_CASE_P(TooManyNames, BdpEstimatorRandomTest, } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); gpr_now_impl = grpc_core::testing::fake_gpr_now; grpc_init(); grpc_timer_manager_set_threading(false); diff --git a/test/core/transport/byte_stream_test.cc b/test/core/transport/byte_stream_test.cc index df096372498..6c543892d0a 100644 --- a/test/core/transport/byte_stream_test.cc +++ b/test/core/transport/byte_stream_test.cc @@ -245,7 +245,7 @@ TEST(CachingByteStream, SharedCache) { int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int retval = RUN_ALL_TESTS(); grpc_shutdown(); diff --git a/test/core/transport/chttp2/alpn_test.cc b/test/core/transport/chttp2/alpn_test.cc index a43377393e1..6da5299363b 100644 --- a/test/core/transport/chttp2/alpn_test.cc +++ b/test/core/transport/chttp2/alpn_test.cc @@ -49,7 +49,7 @@ static void test_alpn_grpc_before_h2(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_alpn_success(); test_alpn_failure(); test_alpn_grpc_before_h2(); diff --git a/test/core/transport/chttp2/context_list_test.cc b/test/core/transport/chttp2/context_list_test.cc index e2100899d39..edbe658a89f 100644 --- a/test/core/transport/chttp2/context_list_test.cc +++ b/test/core/transport/chttp2/context_list_test.cc @@ -33,8 +33,12 @@ namespace grpc_core { namespace testing { namespace { + +const uint32_t kByteOffset = 123; + void TestExecuteFlushesListVerifier(void* arg, grpc_core::Timestamps* ts) { - GPR_ASSERT(arg != nullptr); + ASSERT_NE(arg, nullptr); + EXPECT_EQ(ts->byte_offset, kByteOffset); gpr_atm* done = reinterpret_cast(arg); gpr_atm_rel_store(done, static_cast(1)); } @@ -43,7 +47,7 @@ void discard_write(grpc_slice slice) {} /** Tests that all ContextList elements in the list are flushed out on * execute. - * Also tests that arg is passed correctly. + * Also tests that arg and byte_counter are passed correctly. */ TEST(ContextList, ExecuteFlushesList) { grpc_core::ContextList* list = nullptr; @@ -68,14 +72,14 @@ TEST(ContextList, ExecuteFlushesList) { reinterpret_cast(s[i]), &ref, nullptr, nullptr); s[i]->context = &verifier_called[i]; + s[i]->byte_counter = kByteOffset; gpr_atm_rel_store(&verifier_called[i], static_cast(0)); grpc_core::ContextList::Append(&list, s[i]); } grpc_core::Timestamps ts; grpc_core::ContextList::Execute(list, &ts, GRPC_ERROR_NONE); for (auto i = 0; i < kNumElems; i++) { - GPR_ASSERT(gpr_atm_acq_load(&verifier_called[i]) == - static_cast(1)); + EXPECT_EQ(gpr_atm_acq_load(&verifier_called[i]), static_cast(1)); grpc_transport_destroy_stream(reinterpret_cast(t), reinterpret_cast(s[i]), nullptr); @@ -91,7 +95,7 @@ TEST(ContextList, ExecuteFlushesList) { } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/core/transport/chttp2/hpack_encoder_test.cc b/test/core/transport/chttp2/hpack_encoder_test.cc index ab819f90923..6cbc914c7fa 100644 --- a/test/core/transport/chttp2/hpack_encoder_test.cc +++ b/test/core/transport/chttp2/hpack_encoder_test.cc @@ -261,7 +261,7 @@ static void run_test(void (*test)(), const char* name) { int main(int argc, char** argv) { size_t i; grpc_test_only_set_slice_hash_seed(0); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); TEST(test_basic_headers); TEST(test_decode_table_overflow); diff --git a/test/core/transport/chttp2/hpack_parser_test.cc b/test/core/transport/chttp2/hpack_parser_test.cc index 43b6c79e8a9..882ad726b5a 100644 --- a/test/core/transport/chttp2/hpack_parser_test.cc +++ b/test/core/transport/chttp2/hpack_parser_test.cc @@ -208,7 +208,7 @@ static void test_vectors(grpc_slice_split_mode mode) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_vectors(GRPC_SLICE_SPLIT_MERGE_ALL); test_vectors(GRPC_SLICE_SPLIT_ONE_BYTE); diff --git a/test/core/transport/chttp2/hpack_table_test.cc b/test/core/transport/chttp2/hpack_table_test.cc index 3ab463b6312..c31975786f0 100644 --- a/test/core/transport/chttp2/hpack_table_test.cc +++ b/test/core/transport/chttp2/hpack_table_test.cc @@ -268,7 +268,7 @@ static void test_find(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_static_lookup(); test_many_additions(); diff --git a/test/core/transport/chttp2/settings_timeout_test.cc b/test/core/transport/chttp2/settings_timeout_test.cc index 2d6f0a9a629..a9789edbf2b 100644 --- a/test/core/transport/chttp2/settings_timeout_test.cc +++ b/test/core/transport/chttp2/settings_timeout_test.cc @@ -248,7 +248,7 @@ TEST(SettingsTimeout, Basic) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); int result = RUN_ALL_TESTS(); grpc_shutdown(); diff --git a/test/core/transport/chttp2/stream_map_test.cc b/test/core/transport/chttp2/stream_map_test.cc index 773eb3a35f6..a36c496eb1e 100644 --- a/test/core/transport/chttp2/stream_map_test.cc +++ b/test/core/transport/chttp2/stream_map_test.cc @@ -193,7 +193,7 @@ int main(int argc, char** argv) { uint32_t prev = 1; uint32_t tmp; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_no_op(); test_empty_find(); diff --git a/test/core/transport/chttp2/varint_test.cc b/test/core/transport/chttp2/varint_test.cc index 36760d0c723..5e00cc376af 100644 --- a/test/core/transport/chttp2/varint_test.cc +++ b/test/core/transport/chttp2/varint_test.cc @@ -44,7 +44,7 @@ static void test_varint(uint32_t value, uint32_t prefix_bits, uint8_t prefix_or, test_varint(value, prefix_bits, prefix_or, expect, sizeof(expect) - 1) int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); TEST_VARINT(0, 1, 0, "\x00"); TEST_VARINT(128, 1, 0, "\x7f\x01"); diff --git a/test/core/transport/connectivity_state_test.cc b/test/core/transport/connectivity_state_test.cc index cbd6318f528..7c7e3084bf5 100644 --- a/test/core/transport/connectivity_state_test.cc +++ b/test/core/transport/connectivity_state_test.cc @@ -134,7 +134,7 @@ static void test_subscribe_with_failure_then_destroy(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); grpc_core::testing::grpc_tracer_enable_flag(&grpc_connectivity_state_trace); test_connectivity_state_name(); diff --git a/test/core/transport/metadata_test.cc b/test/core/transport/metadata_test.cc index 8ab9639dfa2..9a49d28ccce 100644 --- a/test/core/transport/metadata_test.cc +++ b/test/core/transport/metadata_test.cc @@ -370,7 +370,7 @@ static void test_copied_static_metadata(bool dup_key, bool dup_value) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_no_op(); for (int k = 0; k <= 1; k++) { diff --git a/test/core/transport/pid_controller_test.cc b/test/core/transport/pid_controller_test.cc index 8d2cec40421..f6235244f60 100644 --- a/test/core/transport/pid_controller_test.cc +++ b/test/core/transport/pid_controller_test.cc @@ -85,7 +85,7 @@ INSTANTIATE_TEST_CASE_P( } // namespace grpc_core int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/core/transport/status_conversion_test.cc b/test/core/transport/status_conversion_test.cc index f7b3c62a40d..949be42aeb4 100644 --- a/test/core/transport/status_conversion_test.cc +++ b/test/core/transport/status_conversion_test.cc @@ -163,7 +163,7 @@ static void test_http2_status_to_grpc_status() { int main(int argc, char** argv) { int i; - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); test_grpc_status_to_http2_error(); diff --git a/test/core/transport/stream_owned_slice_test.cc b/test/core/transport/stream_owned_slice_test.cc index 7831f67a048..48a77db9a50 100644 --- a/test/core/transport/stream_owned_slice_test.cc +++ b/test/core/transport/stream_owned_slice_test.cc @@ -26,7 +26,7 @@ static void do_nothing(void* arg, grpc_error* error) {} int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); uint8_t buffer[] = "abc123"; diff --git a/test/core/transport/timeout_encoding_test.cc b/test/core/transport/timeout_encoding_test.cc index b7044b5b410..22e68fe5540 100644 --- a/test/core/transport/timeout_encoding_test.cc +++ b/test/core/transport/timeout_encoding_test.cc @@ -156,7 +156,7 @@ void test_decoding_fails(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_encoding(); test_decoding(); test_decoding_fails(); diff --git a/test/core/tsi/fake_transport_security_test.cc b/test/core/tsi/fake_transport_security_test.cc index 587d8f5dda5..32361f19d3f 100644 --- a/test/core/tsi/fake_transport_security_test.cc +++ b/test/core/tsi/fake_transport_security_test.cc @@ -139,7 +139,7 @@ void fake_tsi_test_do_round_trip_odd_buffer_size() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); fake_tsi_test_do_handshake_tiny_handshake_buffer(); fake_tsi_test_do_handshake_small_handshake_buffer(); diff --git a/test/core/tsi/ssl_session_cache_test.cc b/test/core/tsi/ssl_session_cache_test.cc index c86cefb3ff4..b9c98c0b57c 100644 --- a/test/core/tsi/ssl_session_cache_test.cc +++ b/test/core/tsi/ssl_session_cache_test.cc @@ -145,7 +145,7 @@ TEST(SslSessionCacheTest, LruCache) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); int ret = RUN_ALL_TESTS(); grpc_shutdown(); diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc index baffad6ea36..fc6c6ba3208 100644 --- a/test/core/tsi/ssl_transport_security_test.cc +++ b/test/core/tsi/ssl_transport_security_test.cc @@ -777,7 +777,7 @@ void ssl_tsi_test_handshaker_factory_internals() { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc_init(); ssl_tsi_test_do_handshake_tiny_handshake_buffer(); diff --git a/test/core/tsi/transport_security_test.cc b/test/core/tsi/transport_security_test.cc index 5c92912f6f6..150e5745a8d 100644 --- a/test/core/tsi/transport_security_test.cc +++ b/test/core/tsi/transport_security_test.cc @@ -381,7 +381,7 @@ static void test_handshaker_invalid_state(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_peer_matches_name(); test_result_strings(); test_protector_invalid_args(); diff --git a/test/core/util/cmdline_test.cc b/test/core/util/cmdline_test.cc index 9f5ad88d573..59e1bbff34e 100644 --- a/test/core/util/cmdline_test.cc +++ b/test/core/util/cmdline_test.cc @@ -463,7 +463,7 @@ static void test_badargs4(void) { } int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); test_simple_int(); test_eq_int(); test_2dash_int(); diff --git a/test/core/util/fuzzer_corpus_test.cc b/test/core/util/fuzzer_corpus_test.cc index ebf19131371..6e3785c4f74 100644 --- a/test/core/util/fuzzer_corpus_test.cc +++ b/test/core/util/fuzzer_corpus_test.cc @@ -144,7 +144,7 @@ INSTANTIATE_TEST_CASE_P( ::testing::internal::ParamGenerator(new ExampleGenerator)); int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ParseCommandLineFlags(&argc, &argv, true); ::testing::InitGoogleTest(&argc, argv); diff --git a/test/core/util/test_config.cc b/test/core/util/test_config.cc index 6a0d444a732..fe80bb2d4d0 100644 --- a/test/core/util/test_config.cc +++ b/test/core/util/test_config.cc @@ -397,3 +397,15 @@ void grpc_test_init(int argc, char** argv) { concurrently running test binary */ srand(seed()); } + +namespace grpc { +namespace testing { + +TestEnvironment::TestEnvironment(int argc, char** argv) { + grpc_test_init(argc, argv); +} + +TestEnvironment::~TestEnvironment() {} + +} // namespace testing +} // namespace grpc diff --git a/test/core/util/test_config.h b/test/core/util/test_config.h index 5b3d34799ee..112af3176f9 100644 --- a/test/core/util/test_config.h +++ b/test/core/util/test_config.h @@ -37,6 +37,21 @@ gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms); #define GRPC_TEST_PICK_PORT #endif +// Prefer TestEnvironment below. void grpc_test_init(int argc, char** argv); +namespace grpc { +namespace testing { + +// A TestEnvironment object should be alive in the main function of a test. It +// provides test init and shutdown inside. +class TestEnvironment { + public: + TestEnvironment(int argc, char** argv); + ~TestEnvironment(); +}; + +} // namespace testing +} // namespace grpc + #endif /* GRPC_TEST_CORE_UTIL_TEST_CONFIG_H */ diff --git a/test/cpp/client/client_channel_stress_test.cc b/test/cpp/client/client_channel_stress_test.cc index 976eeb6aeab..bf321d8a89e 100644 --- a/test/cpp/client/client_channel_stress_test.cc +++ b/test/cpp/client/client_channel_stress_test.cc @@ -321,7 +321,7 @@ class ClientChannelStressTest { int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); grpc::testing::ClientChannelStressTest test; test.Run(); grpc_shutdown(); diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden index fdc67969d96..1871e1375ed 100644 --- a/test/cpp/codegen/compiler_test_golden +++ b/test/cpp/codegen/compiler_test_golden @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -117,10 +118,13 @@ class ServiceA final { // // Method A2 leading comment 1 // Method A2 leading comment 2 + virtual void MethodA2(::grpc::ClientContext* context, ::grpc::testing::Response* response, ::grpc::experimental::ClientWriteReactor< ::grpc::testing::Request>* reactor) = 0; // MethodA2 trailing comment 1 // Method A3 leading comment 1 + virtual void MethodA3(::grpc::ClientContext* context, ::grpc::testing::Request* request, ::grpc::experimental::ClientReadReactor< ::grpc::testing::Response>* reactor) = 0; // Method A3 trailing comment 1 // Method A4 leading comment 1 + virtual void MethodA4(::grpc::ClientContext* context, ::grpc::experimental::ClientBidiReactor< ::grpc::testing::Request,::grpc::testing::Response>* reactor) = 0; // Method A4 trailing comment 1 }; virtual class experimental_async_interface* experimental_async() { return nullptr; } @@ -178,6 +182,9 @@ class ServiceA final { public StubInterface::experimental_async_interface { public: void MethodA1(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, std::function) override; + void MethodA2(::grpc::ClientContext* context, ::grpc::testing::Response* response, ::grpc::experimental::ClientWriteReactor< ::grpc::testing::Request>* reactor) override; + void MethodA3(::grpc::ClientContext* context, ::grpc::testing::Request* request, ::grpc::experimental::ClientReadReactor< ::grpc::testing::Response>* reactor) override; + void MethodA4(::grpc::ClientContext* context, ::grpc::experimental::ClientBidiReactor< ::grpc::testing::Request,::grpc::testing::Response>* reactor) override; private: friend class Stub; explicit experimental_async(Stub* stub): stub_(stub) { } @@ -315,13 +322,13 @@ class ServiceA final { public: ExperimentalWithCallbackMethod_MethodA1() { ::grpc::Service::experimental().MarkMethodCallback(0, - new ::grpc::internal::CallbackUnaryHandler< ExperimentalWithCallbackMethod_MethodA1, ::grpc::testing::Request, ::grpc::testing::Response>( + new ::grpc::internal::CallbackUnaryHandler< ::grpc::testing::Request, ::grpc::testing::Response>( [this](::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, ::grpc::experimental::ServerCallbackRpcController* controller) { - this->MethodA1(context, request, response, controller); - }, this)); + return this->MethodA1(context, request, response, controller); + })); } ~ExperimentalWithCallbackMethod_MethodA1() override { BaseClassMustBeDerivedFromService(this); @@ -339,6 +346,9 @@ class ServiceA final { void BaseClassMustBeDerivedFromService(const Service *service) {} public: ExperimentalWithCallbackMethod_MethodA2() { + ::grpc::Service::experimental().MarkMethodCallback(1, + new ::grpc::internal::CallbackClientStreamingHandler< ::grpc::testing::Request, ::grpc::testing::Response>( + [this] { return this->MethodA2(); })); } ~ExperimentalWithCallbackMethod_MethodA2() override { BaseClassMustBeDerivedFromService(this); @@ -348,6 +358,9 @@ class ServiceA final { abort(); return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } + virtual ::grpc::experimental::ServerReadReactor< ::grpc::testing::Request, ::grpc::testing::Response>* MethodA2() { + return new ::grpc::internal::UnimplementedReadReactor< + ::grpc::testing::Request, ::grpc::testing::Response>;} }; template class ExperimentalWithCallbackMethod_MethodA3 : public BaseClass { @@ -355,6 +368,9 @@ class ServiceA final { void BaseClassMustBeDerivedFromService(const Service *service) {} public: ExperimentalWithCallbackMethod_MethodA3() { + ::grpc::Service::experimental().MarkMethodCallback(2, + new ::grpc::internal::CallbackServerStreamingHandler< ::grpc::testing::Request, ::grpc::testing::Response>( + [this] { return this->MethodA3(); })); } ~ExperimentalWithCallbackMethod_MethodA3() override { BaseClassMustBeDerivedFromService(this); @@ -364,6 +380,9 @@ class ServiceA final { abort(); return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } + virtual ::grpc::experimental::ServerWriteReactor< ::grpc::testing::Request, ::grpc::testing::Response>* MethodA3() { + return new ::grpc::internal::UnimplementedWriteReactor< + ::grpc::testing::Request, ::grpc::testing::Response>;} }; template class ExperimentalWithCallbackMethod_MethodA4 : public BaseClass { @@ -371,6 +390,9 @@ class ServiceA final { void BaseClassMustBeDerivedFromService(const Service *service) {} public: ExperimentalWithCallbackMethod_MethodA4() { + ::grpc::Service::experimental().MarkMethodCallback(3, + new ::grpc::internal::CallbackBidiHandler< ::grpc::testing::Request, ::grpc::testing::Response>( + [this] { return this->MethodA4(); })); } ~ExperimentalWithCallbackMethod_MethodA4() override { BaseClassMustBeDerivedFromService(this); @@ -380,6 +402,9 @@ class ServiceA final { abort(); return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } + virtual ::grpc::experimental::ServerBidiReactor< ::grpc::testing::Request, ::grpc::testing::Response>* MethodA4() { + return new ::grpc::internal::UnimplementedBidiReactor< + ::grpc::testing::Request, ::grpc::testing::Response>;} }; typedef ExperimentalWithCallbackMethod_MethodA1 > > > ExperimentalCallbackService; template @@ -537,13 +562,13 @@ class ServiceA final { public: ExperimentalWithRawCallbackMethod_MethodA1() { ::grpc::Service::experimental().MarkMethodRawCallback(0, - new ::grpc::internal::CallbackUnaryHandler< ExperimentalWithRawCallbackMethod_MethodA1, ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this](::grpc::ServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response, ::grpc::experimental::ServerCallbackRpcController* controller) { this->MethodA1(context, request, response, controller); - }, this)); + })); } ~ExperimentalWithRawCallbackMethod_MethodA1() override { BaseClassMustBeDerivedFromService(this); @@ -561,6 +586,9 @@ class ServiceA final { void BaseClassMustBeDerivedFromService(const Service *service) {} public: ExperimentalWithRawCallbackMethod_MethodA2() { + ::grpc::Service::experimental().MarkMethodRawCallback(1, + new ::grpc::internal::CallbackClientStreamingHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this] { return this->MethodA2(); })); } ~ExperimentalWithRawCallbackMethod_MethodA2() override { BaseClassMustBeDerivedFromService(this); @@ -570,6 +598,9 @@ class ServiceA final { abort(); return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } + virtual ::grpc::experimental::ServerReadReactor< ::grpc::ByteBuffer, ::grpc::ByteBuffer>* MethodA2() { + return new ::grpc::internal::UnimplementedReadReactor< + ::grpc::ByteBuffer, ::grpc::ByteBuffer>;} }; template class ExperimentalWithRawCallbackMethod_MethodA3 : public BaseClass { @@ -577,6 +608,9 @@ class ServiceA final { void BaseClassMustBeDerivedFromService(const Service *service) {} public: ExperimentalWithRawCallbackMethod_MethodA3() { + ::grpc::Service::experimental().MarkMethodRawCallback(2, + new ::grpc::internal::CallbackServerStreamingHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this] { return this->MethodA3(); })); } ~ExperimentalWithRawCallbackMethod_MethodA3() override { BaseClassMustBeDerivedFromService(this); @@ -586,6 +620,9 @@ class ServiceA final { abort(); return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } + virtual ::grpc::experimental::ServerWriteReactor< ::grpc::ByteBuffer, ::grpc::ByteBuffer>* MethodA3() { + return new ::grpc::internal::UnimplementedWriteReactor< + ::grpc::ByteBuffer, ::grpc::ByteBuffer>;} }; template class ExperimentalWithRawCallbackMethod_MethodA4 : public BaseClass { @@ -593,6 +630,9 @@ class ServiceA final { void BaseClassMustBeDerivedFromService(const Service *service) {} public: ExperimentalWithRawCallbackMethod_MethodA4() { + ::grpc::Service::experimental().MarkMethodRawCallback(3, + new ::grpc::internal::CallbackBidiHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this] { return this->MethodA4(); })); } ~ExperimentalWithRawCallbackMethod_MethodA4() override { BaseClassMustBeDerivedFromService(this); @@ -602,6 +642,9 @@ class ServiceA final { abort(); return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } + virtual ::grpc::experimental::ServerBidiReactor< ::grpc::ByteBuffer, ::grpc::ByteBuffer>* MethodA4() { + return new ::grpc::internal::UnimplementedBidiReactor< + ::grpc::ByteBuffer, ::grpc::ByteBuffer>;} }; template class WithStreamedUnaryMethod_MethodA1 : public BaseClass { @@ -745,13 +788,13 @@ class ServiceB final { public: ExperimentalWithCallbackMethod_MethodB1() { ::grpc::Service::experimental().MarkMethodCallback(0, - new ::grpc::internal::CallbackUnaryHandler< ExperimentalWithCallbackMethod_MethodB1, ::grpc::testing::Request, ::grpc::testing::Response>( + new ::grpc::internal::CallbackUnaryHandler< ::grpc::testing::Request, ::grpc::testing::Response>( [this](::grpc::ServerContext* context, const ::grpc::testing::Request* request, ::grpc::testing::Response* response, ::grpc::experimental::ServerCallbackRpcController* controller) { - this->MethodB1(context, request, response, controller); - }, this)); + return this->MethodB1(context, request, response, controller); + })); } ~ExperimentalWithCallbackMethod_MethodB1() override { BaseClassMustBeDerivedFromService(this); @@ -808,13 +851,13 @@ class ServiceB final { public: ExperimentalWithRawCallbackMethod_MethodB1() { ::grpc::Service::experimental().MarkMethodRawCallback(0, - new ::grpc::internal::CallbackUnaryHandler< ExperimentalWithRawCallbackMethod_MethodB1, ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this](::grpc::ServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response, ::grpc::experimental::ServerCallbackRpcController* controller) { this->MethodB1(context, request, response, controller); - }, this)); + })); } ~ExperimentalWithRawCallbackMethod_MethodB1() override { BaseClassMustBeDerivedFromService(this); diff --git a/test/cpp/common/alarm_test.cc b/test/cpp/common/alarm_test.cc index e909d03658c..802cdc209a0 100644 --- a/test/cpp/common/alarm_test.cc +++ b/test/cpp/common/alarm_test.cc @@ -313,7 +313,7 @@ TEST(AlarmTest, UnsetDestruction) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 6ecb9578015..e09f54dcc3f 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -1884,7 +1884,7 @@ int main(int argc, char** argv) { // Change the backup poll interval from 5s to 100ms to speed up the // ReconnectChannel test gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "100"); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc index f04ffe4f2d5..29b59e4e5e1 100644 --- a/test/cpp/end2end/channelz_service_test.cc +++ b/test/cpp/end2end/channelz_service_test.cc @@ -677,7 +677,7 @@ TEST_F(ChannelzServerTest, GetServerListenSocketsTest) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/client_callback_end2end_test.cc b/test/cpp/end2end/client_callback_end2end_test.cc index 98bd99fac69..479aaba9774 100644 --- a/test/cpp/end2end/client_callback_end2end_test.cc +++ b/test/cpp/end2end/client_callback_end2end_test.cc @@ -182,6 +182,55 @@ class ClientCallbackEnd2endTest } } + void SendGenericEchoAsBidi(int num_rpcs) { + const grpc::string kMethodName("/grpc.testing.EchoTestService/Echo"); + grpc::string test_string(""); + for (int i = 0; i < num_rpcs; i++) { + test_string += "Hello world. "; + class Client : public grpc::experimental::ClientBidiReactor { + public: + Client(ClientCallbackEnd2endTest* test, const grpc::string& method_name, + const grpc::string& test_str) { + test->generic_stub_->experimental().PrepareBidiStreamingCall( + &cli_ctx_, method_name, this); + request_.set_message(test_str); + send_buf_ = SerializeToByteBuffer(&request_); + StartWrite(send_buf_.get()); + StartRead(&recv_buf_); + StartCall(); + } + void OnWriteDone(bool ok) override { StartWritesDone(); } + void OnReadDone(bool ok) override { + EchoResponse response; + EXPECT_TRUE(ParseFromByteBuffer(&recv_buf_, &response)); + EXPECT_EQ(request_.message(), response.message()); + }; + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + std::unique_lock l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + EchoRequest request_; + std::unique_ptr send_buf_; + ByteBuffer recv_buf_; + ClientContext cli_ctx_; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; + } rpc{this, kMethodName, test_string}; + + rpc.Await(); + } + } bool is_server_started_; std::shared_ptr channel_; std::unique_ptr stub_; @@ -245,6 +294,11 @@ TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcs) { SendRpcsGeneric(10, false); } +TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidi) { + ResetStub(); + SendGenericEchoAsBidi(10); +} + #if GRPC_ALLOW_EXCEPTIONS TEST_P(ClientCallbackEnd2endTest, ExceptingRpc) { ResetStub(); @@ -301,6 +355,156 @@ TEST_P(ClientCallbackEnd2endTest, CancelRpcBeforeStart) { } } +TEST_P(ClientCallbackEnd2endTest, RequestStream) { + ResetStub(); + class Client : public grpc::experimental::ClientWriteReactor { + public: + explicit Client(grpc::testing::EchoTestService::Stub* stub) { + context_.set_initial_metadata_corked(true); + stub->experimental_async()->RequestStream(&context_, &response_, this); + StartCall(); + request_.set_message("Hello server."); + StartWrite(&request_); + } + void OnWriteDone(bool ok) override { + writes_left_--; + if (writes_left_ > 1) { + StartWrite(&request_); + } else if (writes_left_ == 1) { + StartWriteLast(&request_, WriteOptions()); + } + } + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + EXPECT_EQ(response_.message(), "Hello server.Hello server.Hello server."); + std::unique_lock l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + int writes_left_{3}; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; + } test{stub_.get()}; + + test.Await(); +} + +TEST_P(ClientCallbackEnd2endTest, ResponseStream) { + ResetStub(); + class Client : public grpc::experimental::ClientReadReactor { + public: + explicit Client(grpc::testing::EchoTestService::Stub* stub) { + request_.set_message("Hello client "); + stub->experimental_async()->ResponseStream(&context_, &request_, this); + StartCall(); + StartRead(&response_); + } + void OnReadDone(bool ok) override { + if (!ok) { + EXPECT_EQ(reads_complete_, kServerDefaultResponseStreamsToSend); + } else { + EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); + EXPECT_EQ(response_.message(), + request_.message() + grpc::to_string(reads_complete_)); + reads_complete_++; + StartRead(&response_); + } + } + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + std::unique_lock l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + int reads_complete_{0}; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; + } test{stub_.get()}; + + test.Await(); +} + +TEST_P(ClientCallbackEnd2endTest, BidiStream) { + ResetStub(); + class Client : public grpc::experimental::ClientBidiReactor { + public: + explicit Client(grpc::testing::EchoTestService::Stub* stub) { + request_.set_message("Hello fren "); + stub->experimental_async()->BidiStream(&context_, this); + StartCall(); + StartRead(&response_); + StartWrite(&request_); + } + void OnReadDone(bool ok) override { + if (!ok) { + EXPECT_EQ(reads_complete_, kServerDefaultResponseStreamsToSend); + } else { + EXPECT_LE(reads_complete_, kServerDefaultResponseStreamsToSend); + EXPECT_EQ(response_.message(), request_.message()); + reads_complete_++; + StartRead(&response_); + } + } + void OnWriteDone(bool ok) override { + EXPECT_TRUE(ok); + if (++writes_complete_ == kServerDefaultResponseStreamsToSend) { + StartWritesDone(); + } else { + StartWrite(&request_); + } + } + void OnDone(const Status& s) override { + EXPECT_TRUE(s.ok()); + std::unique_lock l(mu_); + done_ = true; + cv_.notify_one(); + } + void Await() { + std::unique_lock l(mu_); + while (!done_) { + cv_.wait(l); + } + } + + private: + EchoRequest request_; + EchoResponse response_; + ClientContext context_; + int reads_complete_{0}; + int writes_complete_{0}; + std::mutex mu_; + std::condition_variable cv_; + bool done_ = false; + } test{stub_.get()}; + + test.Await(); +} + TestScenario scenarios[] = {TestScenario{false}, TestScenario{true}}; INSTANTIATE_TEST_CASE_P(ClientCallbackEnd2endTest, ClientCallbackEnd2endTest, @@ -311,7 +515,7 @@ INSTANTIATE_TEST_CASE_P(ClientCallbackEnd2endTest, ClientCallbackEnd2endTest, } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc index 2a06f44c608..992f3c488f9 100644 --- a/test/cpp/end2end/client_crash_test.cc +++ b/test/cpp/end2end/client_crash_test.cc @@ -135,7 +135,7 @@ int main(int argc, char** argv) { g_root = "."; } - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); // Order seems to matter on these tests: run three times to eliminate that for (int i = 0; i < 3; i++) { diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 60e8b051ab8..3a191d1e038 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -639,7 +639,7 @@ TEST_F(ClientGlobalInterceptorEnd2endTest, HijackingGlobalInterceptor) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index 312065a2dfe..b667460cf08 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -1153,7 +1153,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingInhibitPerChannel) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); const auto result = RUN_ALL_TESTS(); return result; } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 03291e1785c..05cd4330c61 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -196,16 +196,18 @@ class TestServiceImplDupPkg class TestScenario { public: TestScenario(bool interceptors, bool proxy, bool inproc_stub, - const grpc::string& creds_type) + const grpc::string& creds_type, bool use_callback_server) : use_interceptors(interceptors), use_proxy(proxy), inproc(inproc_stub), - credentials_type(creds_type) {} + credentials_type(creds_type), + callback_server(use_callback_server) {} void Log() const; bool use_interceptors; bool use_proxy; bool inproc; const grpc::string credentials_type; + bool callback_server; }; static std::ostream& operator<<(std::ostream& out, @@ -214,6 +216,8 @@ static std::ostream& operator<<(std::ostream& out, << (scenario.use_interceptors ? "true" : "false") << ", use_proxy=" << (scenario.use_proxy ? "true" : "false") << ", inproc=" << (scenario.inproc ? "true" : "false") + << ", server_type=" + << (scenario.callback_server ? "callback" : "sync") << ", credentials='" << scenario.credentials_type << "'}"; } @@ -280,7 +284,11 @@ class End2endTest : public ::testing::TestWithParam { builder.experimental().SetInterceptorCreators(std::move(creators)); } builder.AddListeningPort(server_address_.str(), server_creds); - builder.RegisterService(&service_); + if (!GetParam().callback_server) { + builder.RegisterService(&service_); + } else { + builder.RegisterService(&callback_service_); + } builder.RegisterService("foo.test.youtube.com", &special_service_); builder.RegisterService(&dup_pkg_service_); @@ -362,6 +370,7 @@ class End2endTest : public ::testing::TestWithParam { std::ostringstream server_address_; const int kMaxMessageSize_; TestServiceImpl service_; + CallbackTestServiceImpl callback_service_; TestServiceImpl special_service_; TestServiceImplDupPkg dup_pkg_service_; grpc::string user_agent_prefix_; @@ -1016,7 +1025,8 @@ TEST_P(End2endTest, DiffPackageServices) { EXPECT_TRUE(s.ok()); } -void CancelRpc(ClientContext* context, int delay_us, TestServiceImpl* service) { +template +void CancelRpc(ClientContext* context, int delay_us, ServiceType* service) { gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(delay_us, GPR_TIMESPAN))); while (!service->signal_client()) { @@ -1446,7 +1456,24 @@ TEST_P(ProxyEnd2endTest, ClientCancelsRpc) { request.mutable_param()->set_client_cancel_after_us(kCancelDelayUs); ClientContext context; - std::thread cancel_thread(CancelRpc, &context, kCancelDelayUs, &service_); + std::thread cancel_thread; + if (!GetParam().callback_server) { + cancel_thread = std::thread( + [&context, this](int delay) { CancelRpc(&context, delay, &service_); }, + kCancelDelayUs); + // Note: the unusual pattern above (and below) is caused by a conflict + // between two sets of compiler expectations. clang allows const to be + // captured without mention, so there is no need to capture kCancelDelayUs + // (and indeed clang-tidy complains if you do so). OTOH, a Windows compiler + // in our tests requires an explicit capture even for const. We square this + // circle by passing the const value in as an argument to the lambda. + } else { + cancel_thread = std::thread( + [&context, this](int delay) { + CancelRpc(&context, delay, &callback_service_); + }, + kCancelDelayUs); + } Status s = stub_->Echo(&context, request, &response); cancel_thread.join(); EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); @@ -1838,10 +1865,12 @@ TEST_P(ResourceQuotaEnd2endTest, SimpleRequest) { EXPECT_TRUE(s.ok()); } +// TODO(vjpai): refactor arguments into a struct if it makes sense std::vector CreateTestScenarios(bool use_proxy, bool test_insecure, bool test_secure, - bool test_inproc) { + bool test_inproc, + bool test_callback_server) { std::vector scenarios; std::vector credentials_types; if (test_secure) { @@ -1857,41 +1886,48 @@ std::vector CreateTestScenarios(bool use_proxy, if (test_insecure && insec_ok()) { credentials_types.push_back(kInsecureCredentialsType); } + + // For now test callback server only with inproc GPR_ASSERT(!credentials_types.empty()); for (const auto& cred : credentials_types) { - scenarios.emplace_back(false, false, false, cred); - scenarios.emplace_back(true, false, false, cred); + scenarios.emplace_back(false, false, false, cred, false); + scenarios.emplace_back(true, false, false, cred, false); if (use_proxy) { - scenarios.emplace_back(false, true, false, cred); - scenarios.emplace_back(true, true, false, cred); + scenarios.emplace_back(false, true, false, cred, false); + scenarios.emplace_back(true, true, false, cred, false); } } if (test_inproc && insec_ok()) { - scenarios.emplace_back(false, false, true, kInsecureCredentialsType); - scenarios.emplace_back(true, false, true, kInsecureCredentialsType); + scenarios.emplace_back(false, false, true, kInsecureCredentialsType, false); + scenarios.emplace_back(true, false, true, kInsecureCredentialsType, false); + if (test_callback_server) { + scenarios.emplace_back(false, false, true, kInsecureCredentialsType, + true); + scenarios.emplace_back(true, false, true, kInsecureCredentialsType, true); + } } return scenarios; } -INSTANTIATE_TEST_CASE_P(End2end, End2endTest, - ::testing::ValuesIn(CreateTestScenarios(false, true, - true, true))); +INSTANTIATE_TEST_CASE_P( + End2end, End2endTest, + ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); -INSTANTIATE_TEST_CASE_P(End2endServerTryCancel, End2endServerTryCancelTest, - ::testing::ValuesIn(CreateTestScenarios(false, true, - true, true))); +INSTANTIATE_TEST_CASE_P( + End2endServerTryCancel, End2endServerTryCancelTest, + ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true))); -INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(true, true, - true, true))); +INSTANTIATE_TEST_CASE_P( + ProxyEnd2end, ProxyEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(true, true, true, true, false))); -INSTANTIATE_TEST_CASE_P(SecureEnd2end, SecureEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(false, false, - true, false))); +INSTANTIATE_TEST_CASE_P( + SecureEnd2end, SecureEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(false, false, true, false, true))); -INSTANTIATE_TEST_CASE_P(ResourceQuotaEnd2end, ResourceQuotaEnd2endTest, - ::testing::ValuesIn(CreateTestScenarios(false, true, - true, true))); +INSTANTIATE_TEST_CASE_P( + ResourceQuotaEnd2end, ResourceQuotaEnd2endTest, + ::testing::ValuesIn(CreateTestScenarios(false, true, true, true, false))); } // namespace } // namespace testing @@ -1899,7 +1935,7 @@ INSTANTIATE_TEST_CASE_P(ResourceQuotaEnd2end, ResourceQuotaEnd2endTest, int main(int argc, char** argv) { gpr_setenv("GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS", "200"); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/exception_test.cc b/test/cpp/end2end/exception_test.cc index 5343997663e..0d2c00263b7 100644 --- a/test/cpp/end2end/exception_test.cc +++ b/test/cpp/end2end/exception_test.cc @@ -117,7 +117,7 @@ TEST_F(ExceptionTest, RequestStream) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/filter_end2end_test.cc b/test/cpp/end2end/filter_end2end_test.cc index 88f8f380c3a..ad67402e3df 100644 --- a/test/cpp/end2end/filter_end2end_test.cc +++ b/test/cpp/end2end/filter_end2end_test.cc @@ -331,7 +331,7 @@ void RegisterFilter() { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); grpc::testing::RegisterFilter(); return RUN_ALL_TESTS(); diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc index 88a1227ca2e..015862bfe81 100644 --- a/test/cpp/end2end/generic_end2end_test.cc +++ b/test/cpp/end2end/generic_end2end_test.cc @@ -333,7 +333,7 @@ TEST_F(GenericEnd2endTest, Deadline) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index 6ce0696114e..9c4cd050619 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -553,10 +553,11 @@ class GrpclbEnd2endTest : public ::testing::Test { return status; } - void CheckRpcSendOk(const size_t times = 1, const int timeout_ms = 1000) { + void CheckRpcSendOk(const size_t times = 1, const int timeout_ms = 1000, + bool wait_for_ready = false) { for (size_t i = 0; i < times; ++i) { EchoResponse response; - const Status status = SendRpc(&response, timeout_ms); + const Status status = SendRpc(&response, timeout_ms, wait_for_ready); EXPECT_TRUE(status.ok()) << "code=" << status.error_code() << " message=" << status.error_message(); EXPECT_EQ(response.message(), kRequestMessage_); @@ -717,10 +718,9 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) { ScheduleResponseForBalancer( 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), kServerlistDelayMs); - const auto t0 = system_clock::now(); // Client will block: LB will initially send empty serverlist. - CheckRpcSendOk(1, kCallDeadlineMs); + CheckRpcSendOk(1, kCallDeadlineMs, true /* wait_for_ready */); const auto ellapsed_ms = std::chrono::duration_cast( system_clock::now() - t0); @@ -1518,7 +1518,7 @@ TEST_F(SingleBalancerWithClientLoadReportingTest, Drop) { int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); const auto result = RUN_ALL_TESTS(); grpc_shutdown(); diff --git a/test/cpp/end2end/health_service_end2end_test.cc b/test/cpp/end2end/health_service_end2end_test.cc index fca65dfc13b..89c4bef09cf 100644 --- a/test/cpp/end2end/health_service_end2end_test.cc +++ b/test/cpp/end2end/health_service_end2end_test.cc @@ -331,7 +331,7 @@ TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/hybrid_end2end_test.cc b/test/cpp/end2end/hybrid_end2end_test.cc index 339eadde92e..18bb1ff4b96 100644 --- a/test/cpp/end2end/hybrid_end2end_test.cc +++ b/test/cpp/end2end/hybrid_end2end_test.cc @@ -894,7 +894,7 @@ TEST_F(HybridEnd2endTest, GenericMethodWithoutGenericService) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc index ba3122c895f..917ca28020a 100644 --- a/test/cpp/end2end/mock_test.cc +++ b/test/cpp/end2end/mock_test.cc @@ -345,7 +345,7 @@ TEST_F(MockTest, BidiStream) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/nonblocking_test.cc b/test/cpp/end2end/nonblocking_test.cc index d8337baca22..36dea1fcb31 100644 --- a/test/cpp/end2end/nonblocking_test.cc +++ b/test/cpp/end2end/nonblocking_test.cc @@ -187,7 +187,7 @@ int main(int argc, char** argv) { grpc_poll_function = maybe_assert_non_blocking_poll; #endif // GRPC_POSIX_SOCKET - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; diff --git a/test/cpp/end2end/proto_server_reflection_test.cc b/test/cpp/end2end/proto_server_reflection_test.cc index 21a275ef62c..ff097aa9a77 100644 --- a/test/cpp/end2end/proto_server_reflection_test.cc +++ b/test/cpp/end2end/proto_server_reflection_test.cc @@ -144,7 +144,7 @@ TEST_F(ProtoServerReflectionTest, CheckResponseWithLocalDescriptorPool) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/raw_end2end_test.cc b/test/cpp/end2end/raw_end2end_test.cc index a413905ef7a..c8556bae954 100644 --- a/test/cpp/end2end/raw_end2end_test.cc +++ b/test/cpp/end2end/raw_end2end_test.cc @@ -363,7 +363,7 @@ TEST_F(RawEnd2EndTest, CompileTest) { int main(int argc, char** argv) { // Change the backup poll interval from 5s to 100ms to speed up the // ReconnectChannel test - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); int ret = RUN_ALL_TESTS(); return ret; diff --git a/test/cpp/end2end/server_builder_plugin_test.cc b/test/cpp/end2end/server_builder_plugin_test.cc index d54523fcbb1..d744a93912e 100644 --- a/test/cpp/end2end/server_builder_plugin_test.cc +++ b/test/cpp/end2end/server_builder_plugin_test.cc @@ -264,7 +264,7 @@ INSTANTIATE_TEST_CASE_P(ServerBuilderPluginTest, ServerBuilderPluginTest, } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc index 93257b2705c..353ebf713a0 100644 --- a/test/cpp/end2end/server_crash_test.cc +++ b/test/cpp/end2end/server_crash_test.cc @@ -153,7 +153,7 @@ int main(int argc, char** argv) { g_root = "."; } - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/server_early_return_test.cc b/test/cpp/end2end/server_early_return_test.cc index 8948e5b8546..c47e25052e2 100644 --- a/test/cpp/end2end/server_early_return_test.cc +++ b/test/cpp/end2end/server_early_return_test.cc @@ -226,7 +226,7 @@ TEST_F(ServerEarlyReturnTest, RequestStreamEarlyCancel) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/server_interceptors_end2end_test.cc b/test/cpp/end2end/server_interceptors_end2end_test.cc index 295d63516bd..c98b6143c66 100644 --- a/test/cpp/end2end/server_interceptors_end2end_test.cc +++ b/test/cpp/end2end/server_interceptors_end2end_test.cc @@ -577,7 +577,7 @@ TEST_F(ServerInterceptorsSyncUnimplementedEnd2endTest, UnimplementedRpcTest) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc index a53de691bcd..da42178d67c 100644 --- a/test/cpp/end2end/shutdown_test.cc +++ b/test/cpp/end2end/shutdown_test.cc @@ -164,7 +164,7 @@ TEST_P(ShutdownTest, ShutdownTest) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/streaming_throughput_test.cc b/test/cpp/end2end/streaming_throughput_test.cc index 898d1ec1188..440656588b2 100644 --- a/test/cpp/end2end/streaming_throughput_test.cc +++ b/test/cpp/end2end/streaming_throughput_test.cc @@ -187,7 +187,7 @@ TEST_F(End2endTest, StreamingThroughput) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc index 4eefe58fa7c..6729ad14f4a 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -87,6 +87,46 @@ int MetadataMatchCount( } } // namespace +namespace { +int GetIntValueFromMetadataHelper( + const char* key, + const std::multimap& metadata, + int default_value) { + if (metadata.find(key) != metadata.end()) { + std::istringstream iss(ToString(metadata.find(key)->second)); + iss >> default_value; + gpr_log(GPR_INFO, "%s : %d", key, default_value); + } + + return default_value; +} + +int GetIntValueFromMetadata( + const char* key, + const std::multimap& metadata, + int default_value) { + return GetIntValueFromMetadataHelper(key, metadata, default_value); +} + +void ServerTryCancel(ServerContext* context) { + EXPECT_FALSE(context->IsCancelled()); + context->TryCancel(); + gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); + // Now wait until it's really canceled + while (!context->IsCancelled()) { + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000, GPR_TIMESPAN))); + } +} + +void ServerTryCancelNonblocking(ServerContext* context) { + EXPECT_FALSE(context->IsCancelled()); + context->TryCancel(); + gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); +} + +} // namespace + Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) { // A bit of sleep to make sure that short deadline tests fail @@ -236,6 +276,7 @@ void CallbackTestServiceImpl::EchoNonDelayed( controller->Finish(Status(static_cast(error.code()), error.error_message(), error.binary_error_details())); + return; } int server_try_cancel = GetIntValueFromMetadata( kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); @@ -264,6 +305,7 @@ void CallbackTestServiceImpl::EchoNonDelayed( return; } + gpr_log(GPR_DEBUG, "Request message was %s", request->message().c_str()); response->set_message(request->message()); MaybeEchoDeadline(context, request, response); if (host_) { @@ -294,7 +336,7 @@ void CallbackTestServiceImpl::EchoNonDelayed( alarm_.experimental().Set( gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(request->param().client_cancel_after_us(), + gpr_time_from_micros(request->param().server_cancel_after_us(), GPR_TIMESPAN)), [controller](bool) { controller->Finish(Status::CANCELLED); }); return; @@ -319,6 +361,7 @@ void CallbackTestServiceImpl::EchoNonDelayed( request->param().debug_info().SerializeAsString(); context->AddTrailingMetadata(kDebugInfoTrailerKey, serialized_debug_info); controller->Finish(Status::CANCELLED); + return; } } if (request->has_param() && @@ -365,7 +408,7 @@ Status TestServiceImpl::RequestStream(ServerContext* context, std::thread* server_try_cancel_thd = nullptr; if (server_try_cancel == CANCEL_DURING_PROCESSING) { server_try_cancel_thd = - new std::thread(&TestServiceImpl::ServerTryCancel, this, context); + new std::thread([context] { ServerTryCancel(context); }); } int num_msgs_read = 0; @@ -420,7 +463,7 @@ Status TestServiceImpl::ResponseStream(ServerContext* context, std::thread* server_try_cancel_thd = nullptr; if (server_try_cancel == CANCEL_DURING_PROCESSING) { server_try_cancel_thd = - new std::thread(&TestServiceImpl::ServerTryCancel, this, context); + new std::thread([context] { ServerTryCancel(context); }); } for (int i = 0; i < server_responses_to_send; i++) { @@ -471,7 +514,7 @@ Status TestServiceImpl::BidiStream( std::thread* server_try_cancel_thd = nullptr; if (server_try_cancel == CANCEL_DURING_PROCESSING) { server_try_cancel_thd = - new std::thread(&TestServiceImpl::ServerTryCancel, this, context); + new std::thread([context] { ServerTryCancel(context); }); } // kServerFinishAfterNReads suggests after how many reads, the server should @@ -505,44 +548,244 @@ Status TestServiceImpl::BidiStream( return Status::OK; } -namespace { -int GetIntValueFromMetadataHelper( - const char* key, - const std::multimap& metadata, - int default_value) { - if (metadata.find(key) != metadata.end()) { - std::istringstream iss(ToString(metadata.find(key)->second)); - iss >> default_value; - gpr_log(GPR_INFO, "%s : %d", key, default_value); - } +experimental::ServerReadReactor* +CallbackTestServiceImpl::RequestStream() { + class Reactor : public ::grpc::experimental::ServerReadReactor { + public: + Reactor() {} + void OnStarted(ServerContext* context, EchoResponse* response) override { + ctx_ = context; + response_ = response; + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by + // the server by calling ServerContext::TryCancel() depending on the + // value: + // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server + // reads any message from the client CANCEL_DURING_PROCESSING: The RPC + // is cancelled while the server is reading messages from the client + // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads + // all the messages from the client + server_try_cancel_ = GetIntValueFromMetadata( + kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + + response_->set_message(""); + + if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + return; + } - return default_value; -} -}; // namespace + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + ctx_->TryCancel(); + // Don't wait for it here + } -int TestServiceImpl::GetIntValueFromMetadata( - const char* key, - const std::multimap& metadata, - int default_value) { - return GetIntValueFromMetadataHelper(key, metadata, default_value); + StartRead(&request_); + } + void OnDone() override { delete this; } + void OnCancel() override { FinishOnce(Status::CANCELLED); } + void OnReadDone(bool ok) override { + if (ok) { + response_->mutable_message()->append(request_.message()); + num_msgs_read_++; + StartRead(&request_); + } else { + gpr_log(GPR_INFO, "Read: %d messages", num_msgs_read_); + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + // Let OnCancel recover this + return; + } + if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + return; + } + FinishOnce(Status::OK); + } + } + + private: + void FinishOnce(const Status& s) { + std::lock_guard l(finish_mu_); + if (!finished_) { + Finish(s); + finished_ = true; + } + } + + ServerContext* ctx_; + EchoResponse* response_; + EchoRequest request_; + int num_msgs_read_{0}; + int server_try_cancel_; + std::mutex finish_mu_; + bool finished_{false}; + }; + + return new Reactor; } -int CallbackTestServiceImpl::GetIntValueFromMetadata( - const char* key, - const std::multimap& metadata, - int default_value) { - return GetIntValueFromMetadataHelper(key, metadata, default_value); +// Return 'kNumResponseStreamMsgs' messages. +// TODO(yangg) make it generic by adding a parameter into EchoRequest +experimental::ServerWriteReactor* +CallbackTestServiceImpl::ResponseStream() { + class Reactor + : public ::grpc::experimental::ServerWriteReactor { + public: + Reactor() {} + void OnStarted(ServerContext* context, + const EchoRequest* request) override { + ctx_ = context; + request_ = request; + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by + // the server by calling ServerContext::TryCancel() depending on the + // value: + // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server + // reads any message from the client CANCEL_DURING_PROCESSING: The RPC + // is cancelled while the server is reading messages from the client + // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads + // all the messages from the client + server_try_cancel_ = GetIntValueFromMetadata( + kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + server_coalescing_api_ = GetIntValueFromMetadata( + kServerUseCoalescingApi, context->client_metadata(), 0); + server_responses_to_send_ = GetIntValueFromMetadata( + kServerResponseStreamsToSend, context->client_metadata(), + kServerDefaultResponseStreamsToSend); + if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + return; + } + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + ctx_->TryCancel(); + } + if (num_msgs_sent_ < server_responses_to_send_) { + NextWrite(); + } + } + void OnDone() override { delete this; } + void OnCancel() override { FinishOnce(Status::CANCELLED); } + void OnWriteDone(bool ok) override { + if (num_msgs_sent_ < server_responses_to_send_) { + NextWrite(); + } else if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + // Let OnCancel recover this + } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + } else { + FinishOnce(Status::OK); + } + } + + private: + void FinishOnce(const Status& s) { + std::lock_guard l(finish_mu_); + if (!finished_) { + Finish(s); + finished_ = true; + } + } + + void NextWrite() { + response_.set_message(request_->message() + + grpc::to_string(num_msgs_sent_)); + if (num_msgs_sent_ == server_responses_to_send_ - 1 && + server_coalescing_api_ != 0) { + num_msgs_sent_++; + StartWriteLast(&response_, WriteOptions()); + } else { + num_msgs_sent_++; + StartWrite(&response_); + } + } + ServerContext* ctx_; + const EchoRequest* request_; + EchoResponse response_; + int num_msgs_sent_{0}; + int server_try_cancel_; + int server_coalescing_api_; + int server_responses_to_send_; + std::mutex finish_mu_; + bool finished_{false}; + }; + return new Reactor; } -void TestServiceImpl::ServerTryCancel(ServerContext* context) { - EXPECT_FALSE(context->IsCancelled()); - context->TryCancel(); - gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request"); - // Now wait until it's really canceled - while (!context->IsCancelled()) { - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(1000, GPR_TIMESPAN))); - } +experimental::ServerBidiReactor* +CallbackTestServiceImpl::BidiStream() { + class Reactor : public ::grpc::experimental::ServerBidiReactor { + public: + Reactor() {} + void OnStarted(ServerContext* context) override { + ctx_ = context; + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by + // the server by calling ServerContext::TryCancel() depending on the + // value: + // CANCEL_BEFORE_PROCESSING: The RPC is cancelled before the server + // reads any message from the client CANCEL_DURING_PROCESSING: The RPC + // is cancelled while the server is reading messages from the client + // CANCEL_AFTER_PROCESSING: The RPC is cancelled after the server reads + // all the messages from the client + server_try_cancel_ = GetIntValueFromMetadata( + kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); + server_write_last_ = GetIntValueFromMetadata( + kServerFinishAfterNReads, context->client_metadata(), 0); + if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + return; + } + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + ctx_->TryCancel(); + } + + StartRead(&request_); + } + void OnDone() override { delete this; } + void OnCancel() override { FinishOnce(Status::CANCELLED); } + void OnReadDone(bool ok) override { + if (ok) { + num_msgs_read_++; + gpr_log(GPR_INFO, "recv msg %s", request_.message().c_str()); + response_.set_message(request_.message()); + if (num_msgs_read_ == server_write_last_) { + StartWriteLast(&response_, WriteOptions()); + } else { + StartWrite(&response_); + } + } else if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + // Let OnCancel handle this + } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { + ServerTryCancelNonblocking(ctx_); + } else { + FinishOnce(Status::OK); + } + } + void OnWriteDone(bool ok) override { StartRead(&request_); } + + private: + void FinishOnce(const Status& s) { + std::lock_guard l(finish_mu_); + if (!finished_) { + Finish(s); + finished_ = true; + } + } + + ServerContext* ctx_; + EchoRequest request_; + EchoResponse response_; + int num_msgs_read_{0}; + int server_try_cancel_; + int server_write_last_; + std::mutex finish_mu_; + bool finished_{false}; + }; + + return new Reactor; } } // namespace testing diff --git a/test/cpp/end2end/test_service_impl.h b/test/cpp/end2end/test_service_impl.h index ad0b230907a..e36423d44e4 100644 --- a/test/cpp/end2end/test_service_impl.h +++ b/test/cpp/end2end/test_service_impl.h @@ -78,13 +78,6 @@ class TestServiceImpl : public ::grpc::testing::EchoTestService::Service { } private: - int GetIntValueFromMetadata( - const char* key, - const std::multimap& metadata, - int default_value); - - void ServerTryCancel(ServerContext* context); - bool signal_client_; std::mutex mu_; std::unique_ptr host_; @@ -106,6 +99,15 @@ class CallbackTestServiceImpl SimpleResponse* response, experimental::ServerCallbackRpcController* controller) override; + experimental::ServerReadReactor* RequestStream() + override; + + experimental::ServerWriteReactor* ResponseStream() + override; + + experimental::ServerBidiReactor* BidiStream() + override; + // Unimplemented is left unimplemented to test the returned error. bool signal_client() { std::unique_lock lock(mu_); @@ -117,11 +119,6 @@ class CallbackTestServiceImpl EchoResponse* response, experimental::ServerCallbackRpcController* controller); - int GetIntValueFromMetadata( - const char* key, - const std::multimap& metadata, - int default_value); - Alarm alarm_; bool signal_client_; std::mutex mu_; diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index 1a5ed28a2cc..e30ce0dbcbf 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -429,7 +429,7 @@ TYPED_TEST(AsyncClientEnd2endTest, ThreadStress) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc index 664504a0903..73394028309 100644 --- a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc +++ b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc @@ -370,7 +370,7 @@ TEST_F(StatsPluginEnd2EndTest, RequestReceivedMessagesPerRpc) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc index 85767c8758f..dca97c85b19 100644 --- a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc +++ b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc @@ -94,6 +94,7 @@ static const grpc_event_engine_vtable* init_engine_vtable(bool) { g_vtable.pollset_destroy = pollset_destroy; g_vtable.pollset_work = pollset_work; g_vtable.pollset_kick = pollset_kick; + g_vtable.shutdown_background_closure = [] {}; g_vtable.shutdown_engine = [] {}; return &g_vtable; diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index fc6721d0ba8..3eb0e7d7254 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -838,7 +838,7 @@ int main(int argc, char** argv) { gpr_log(GPR_INFO, "GRPC_DNS_RESOLVER != ares: %s.", resolver); } gpr_free(resolver); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); auto result = RUN_ALL_TESTS(); // Test sequential and nested inits and shutdowns. diff --git a/test/cpp/naming/cancel_ares_query_test.cc b/test/cpp/naming/cancel_ares_query_test.cc index dec7c171dc0..3e789f0b149 100644 --- a/test/cpp/naming/cancel_ares_query_test.cc +++ b/test/cpp/naming/cancel_ares_query_test.cc @@ -260,8 +260,15 @@ TEST(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) { grpc_pollset_set_destroy(fake_other_pollset_set); } -TEST(CancelDuringAresQuery, - TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful) { +// Settings for TestCancelDuringActiveQuery test +typedef enum { + NONE, + SHORT, + ZERO, +} cancellation_test_query_timeout_setting; + +void TestCancelDuringActiveQuery( + cancellation_test_query_timeout_setting query_timeout_setting) { // Start up fake non responsive DNS server int fake_dns_port = grpc_pick_unused_port_or_die(); FakeNonResponsiveDNSServer fake_dns_server(fake_dns_port); @@ -271,9 +278,33 @@ TEST(CancelDuringAresQuery, &client_target, "dns://[::1]:%d/dont-care-since-wont-be-resolved.test.com:1234", fake_dns_port)); + gpr_log(GPR_DEBUG, "TestCancelActiveDNSQuery. query timeout setting: %d", + query_timeout_setting); + grpc_channel_args* client_args = nullptr; + grpc_status_code expected_status_code = GRPC_STATUS_OK; + if (query_timeout_setting == NONE) { + expected_status_code = GRPC_STATUS_DEADLINE_EXCEEDED; + client_args = nullptr; + } else if (query_timeout_setting == SHORT) { + expected_status_code = GRPC_STATUS_UNAVAILABLE; + grpc_arg arg; + arg.type = GRPC_ARG_INTEGER; + arg.key = const_cast(GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS); + arg.value.integer = + 1; // Set this shorter than the call deadline so that it goes off. + client_args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); + } else if (query_timeout_setting == ZERO) { + expected_status_code = GRPC_STATUS_DEADLINE_EXCEEDED; + grpc_arg arg; + arg.type = GRPC_ARG_INTEGER; + arg.key = const_cast(GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS); + arg.value.integer = 0; // Set this to zero to disable query timeouts. + client_args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); + } else { + abort(); + } grpc_channel* client = - grpc_insecure_channel_create(client_target, - /* client_args */ nullptr, nullptr); + grpc_insecure_channel_create(client_target, client_args, nullptr); gpr_free(client_target); grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr); cq_verifier* cqv = cq_verifier_create(cq); @@ -325,8 +356,9 @@ TEST(CancelDuringAresQuery, EXPECT_EQ(GRPC_CALL_OK, error); CQ_EXPECT_COMPLETION(cqv, Tag(1), 1); cq_verify(cqv); - EXPECT_EQ(status, GRPC_STATUS_DEADLINE_EXCEEDED); + EXPECT_EQ(status, expected_status_code); // Teardown + grpc_channel_args_destroy(client_args); grpc_slice_unref(details); gpr_free((void*)error_string); grpc_metadata_array_destroy(&initial_metadata_recv); @@ -338,10 +370,27 @@ TEST(CancelDuringAresQuery, EndTest(client, cq); } +TEST(CancelDuringAresQuery, + TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful) { + TestCancelDuringActiveQuery(NONE /* don't set query timeouts */); +} + +TEST( + CancelDuringAresQuery, + TestHitDeadlineAndDestroyChannelDuringAresResolutionWithQueryTimeoutIsGraceful) { + TestCancelDuringActiveQuery(SHORT /* set short query timeout */); +} + +TEST( + CancelDuringAresQuery, + TestHitDeadlineAndDestroyChannelDuringAresResolutionWithZeroQueryTimeoutIsGraceful) { + TestCancelDuringActiveQuery(ZERO /* disable query timeouts */); +} + } // namespace int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); gpr_setenv("GRPC_DNS_RESOLVER", "ares"); // Sanity check the time that it takes to run the test diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc index 3dc6e7178cc..fe6fcb8d9cb 100644 --- a/test/cpp/naming/resolver_component_test.cc +++ b/test/cpp/naming/resolver_component_test.cc @@ -477,7 +477,7 @@ TEST(ResolverComponentTest, TestResolvesRelevantRecordsWithConcurrentFdStress) { int main(int argc, char** argv) { grpc_init(); - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); ParseCommandLineFlags(&argc, &argv, true); if (FLAGS_target_name == "") { diff --git a/test/cpp/performance/writes_per_rpc_test.cc b/test/cpp/performance/writes_per_rpc_test.cc index baeede34ea4..3c5b3468848 100644 --- a/test/cpp/performance/writes_per_rpc_test.cc +++ b/test/cpp/performance/writes_per_rpc_test.cc @@ -255,7 +255,7 @@ TEST(WritesPerRpcTest, UnaryPingPong) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD index 26f43284a68..626ac5f3f2e 100644 --- a/test/cpp/qps/BUILD +++ b/test/cpp/qps/BUILD @@ -170,7 +170,7 @@ grpc_cc_test( grpc_cc_test( name = "qps_openloop_test", srcs = ["qps_openloop_test.cc"], - data = ["//third_party/toolchains:RBE_USE_MACHINE_TYPE_LARGE"], + exec_compatible_with = ["//third_party/toolchains/machine_size:large"], deps = [ ":benchmark_config", ":driver_impl", diff --git a/test/cpp/server/load_reporter/get_cpu_stats_test.cc b/test/cpp/server/load_reporter/get_cpu_stats_test.cc index 5b1d5fa3a49..98c15b2c69b 100644 --- a/test/cpp/server/load_reporter/get_cpu_stats_test.cc +++ b/test/cpp/server/load_reporter/get_cpu_stats_test.cc @@ -55,7 +55,7 @@ TEST(GetCpuStatsTest, Ascending) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/server/load_reporter/load_data_store_test.cc b/test/cpp/server/load_reporter/load_data_store_test.cc index c92c407e4f8..a3a67a28516 100644 --- a/test/cpp/server/load_reporter/load_data_store_test.cc +++ b/test/cpp/server/load_reporter/load_data_store_test.cc @@ -475,7 +475,7 @@ TEST_F(PerBalancerStoreTest, DataAggregation) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/server/load_reporter/load_reporter_test.cc b/test/cpp/server/load_reporter/load_reporter_test.cc index 0d56cdf431d..9d2ebfb0b4f 100644 --- a/test/cpp/server/load_reporter/load_reporter_test.cc +++ b/test/cpp/server/load_reporter/load_reporter_test.cc @@ -501,7 +501,7 @@ TEST_F(LoadReportTest, BasicReport) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc index 516f3fa53dc..1d641535e29 100644 --- a/test/cpp/util/cli_call_test.cc +++ b/test/cpp/util/cli_call_test.cc @@ -122,7 +122,7 @@ TEST_F(CliCallTest, SimpleRpc) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc index be9a624a2c2..4ddc11c5a64 100644 --- a/test/cpp/util/grpc_tool_test.cc +++ b/test/cpp/util/grpc_tool_test.cc @@ -1173,7 +1173,7 @@ TEST_F(GrpcToolTest, ListCommand_OverrideSslHostName) { } // namespace grpc int main(int argc, char** argv) { - grpc_test_init(argc, argv); + grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); ::testing::FLAGS_gtest_death_test_style = "threadsafe"; return RUN_ALL_TESTS(); diff --git a/third_party/toolchains/BUILD b/third_party/toolchains/BUILD index 02cd87a7b9b..e213461acc9 100644 --- a/third_party/toolchains/BUILD +++ b/third_party/toolchains/BUILD @@ -16,37 +16,72 @@ licenses(["notice"]) # Apache v2 package(default_visibility = ["//visibility:public"]) -exports_files(["RBE_USE_MACHINE_TYPE_LARGE",]) - # Latest RBE Ubuntu16_04 container # Update every time when a new container is released. alias( name = "rbe_ubuntu1604", - actual = ":rbe_ubuntu1604_r328903", + actual = ":rbe_ubuntu1604_r342117", +) + +alias( + name = "rbe_ubuntu1604_large", + actual = ":rbe_ubuntu1604_r342117_large", ) -# RBE Ubuntu16_04 r328903 +# RBE Ubuntu16_04 r342117 platform( - name = "rbe_ubuntu1604_r328903", + name = "rbe_ubuntu1604_r342117", constraint_values = [ "@bazel_tools//platforms:x86_64", "@bazel_tools//platforms:linux", "@bazel_tools//tools/cpp:clang", "@com_github_bazelbuild_bazeltoolchains//constraints:xenial", "@com_github_bazelbuild_bazeltoolchains//constraints/sanitizers:support_msan", + "//third_party/toolchains/machine_size:standard", ], remote_execution_properties = """ properties: { name: "container-image" - value:"docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:59bf0e191a6b5cc1ab62c2224c810681d1326bad5a27b1d36c9f40113e79da7f" + value:"docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:f3120a030a19d67626ababdac79cc787e699a1aa924081431285118f87e7b375" } properties: { name: "gceMachineType" # Small machines for majority of tests. value: "n1-highmem-2" } + """, +) + +# RBE Ubuntu16_04 r342117 large +platform( + name = "rbe_ubuntu1604_r342117_large", + constraint_values = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:linux", + "@bazel_tools//tools/cpp:clang", + "@com_github_bazelbuild_bazeltoolchains//constraints:xenial", + "@com_github_bazelbuild_bazeltoolchains//constraints/sanitizers:support_msan", + "//third_party/toolchains/machine_size:large", + ], + remote_execution_properties = """ + properties: { + name: "container-image" + value:"docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:f3120a030a19d67626ababdac79cc787e699a1aa924081431285118f87e7b375" + } properties: { - name: "gceMachineType_LARGE" # Large machines for a small set of resource-consuming tests such as combiner_tests under TSAN. + name: "gceMachineType" # Large machines for some resource demanding tests (TSAN). value: "n1-standard-8" } - """, + """, +) + +# This target is auto-generated from release/cpp.tpl and should not be +# modified directly. +toolchain( + name = "cc-toolchain-clang-x86_64-default", + exec_compatible_with = [ + ], + target_compatible_with = [ + ], + toolchain = "@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.16.1/default:cc-compiler-k8", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", ) diff --git a/third_party/toolchains/RBE_USE_MACHINE_TYPE_LARGE b/third_party/toolchains/RBE_USE_MACHINE_TYPE_LARGE deleted file mode 100644 index b1120238d7e..00000000000 --- a/third_party/toolchains/RBE_USE_MACHINE_TYPE_LARGE +++ /dev/null @@ -1 +0,0 @@ -# This file is a sentinel and is meant to be empty. diff --git a/third_party/toolchains/machine_size/BUILD b/third_party/toolchains/machine_size/BUILD new file mode 100644 index 00000000000..cc962946c31 --- /dev/null +++ b/third_party/toolchains/machine_size/BUILD @@ -0,0 +1,31 @@ +# Copyright 2018 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +licenses(["notice"]) # Apache v2 + +package(default_visibility = ["//visibility:public"]) + +constraint_setting(name = "machine_size") + +constraint_value( + name = "large", + constraint_setting = ":machine_size", +) + +constraint_value( + name = "standard", + constraint_setting = ":machine_size", +) + +# Add other constraint values as needed (tiny, huge, etc.) in the future. diff --git a/tools/distrib/pylint_code.sh b/tools/distrib/pylint_code.sh index 82a818cce5a..d17eb9fdb82 100755 --- a/tools/distrib/pylint_code.sh +++ b/tools/distrib/pylint_code.sh @@ -20,6 +20,7 @@ cd "$(dirname "$0")/../.." DIRS=( 'src/python/grpcio/grpc' + 'src/python/grpcio_channelz/grpc_channelz' 'src/python/grpcio_health_checking/grpc_health' 'src/python/grpcio_reflection/grpc_reflection' 'src/python/grpcio_testing/grpc_testing' diff --git a/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile index b2216c79d4c..b49fa104105 100644 --- a/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM debian:jessie +FROM debian:stretch # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -67,37 +67,36 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t #================ # C# dependencies -# Update to a newer version of mono -RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF -RUN echo "deb http://download.mono-project.com/repo/debian jessie main" | tee /etc/apt/sources.list.d/mono-official.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list +# cmake >=3.6 needed to build grpc_csharp_ext +RUN apt-get update && apt-get install -y cmake && apt-get clean -# Install dependencies -RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \ +# Install mono +RUN apt-get update && apt-get install -y apt-transport-https dirmngr && apt-get clean +RUN apt-key adv --no-tty --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF +RUN echo "deb https://download.mono-project.com/repo/debian stable-stretch main" | tee /etc/apt/sources.list.d/mono-official-stable.list +RUN apt-get update && apt-get install -y \ mono-devel \ ca-certificates-mono \ nuget \ && apt-get clean -RUN nuget update -self +# Install dotnet SDK +ENV DOTNET_SDK_VERSION 2.1.500 +RUN curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$DOTNET_SDK_VERSION/dotnet-sdk-$DOTNET_SDK_VERSION-linux-x64.tar.gz \ + && mkdir -p /usr/share/dotnet \ + && tar -zxf dotnet.tar.gz -C /usr/share/dotnet \ + && rm dotnet.tar.gz \ + && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet -#================= -# Use cmake 3.6 from jessie-backports -# needed to build grpc_csharp_ext with cmake -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +# Install .NET Core 1.1.10 runtime (required to run netcoreapp1.1) +RUN curl -sSL -o dotnet_old.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/1.1.10/dotnet-debian.9-x64.1.1.10.tar.gz \ + && mkdir -p dotnet_old \ + && tar zxf dotnet_old.tar.gz -C dotnet_old \ + && cp -r dotnet_old/shared/Microsoft.NETCore.App/1.1.10/ /usr/share/dotnet/shared/Microsoft.NETCore.App/ \ + && rm -rf dotnet_old/ dotnet_old.tar.gz +RUN apt-get update && apt-get install -y libunwind8 && apt-get clean -# Install dotnet SDK based on https://www.microsoft.com/net/core#debian -RUN apt-get update && apt-get install -y curl libunwind8 gettext -# dotnet-dev-1.0.0-preview2-003131 -RUN curl -sSL -o dotnet100.tar.gz https://go.microsoft.com/fwlink/?LinkID=827530 -RUN mkdir -p /opt/dotnet && tar zxf dotnet100.tar.gz -C /opt/dotnet -# dotnet-dev-1.0.1 -RUN curl -sSL -o dotnet101.tar.gz https://go.microsoft.com/fwlink/?LinkID=843453 -RUN mkdir -p /opt/dotnet && tar zxf dotnet101.tar.gz -C /opt/dotnet -RUN ln -s /opt/dotnet/dotnet /usr/local/bin # Trigger the population of the local package cache ENV NUGET_XMLDOC_MODE skip diff --git a/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile index b2216c79d4c..b49fa104105 100644 --- a/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM debian:jessie +FROM debian:stretch # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -67,37 +67,36 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t #================ # C# dependencies -# Update to a newer version of mono -RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF -RUN echo "deb http://download.mono-project.com/repo/debian jessie main" | tee /etc/apt/sources.list.d/mono-official.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list +# cmake >=3.6 needed to build grpc_csharp_ext +RUN apt-get update && apt-get install -y cmake && apt-get clean -# Install dependencies -RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \ +# Install mono +RUN apt-get update && apt-get install -y apt-transport-https dirmngr && apt-get clean +RUN apt-key adv --no-tty --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF +RUN echo "deb https://download.mono-project.com/repo/debian stable-stretch main" | tee /etc/apt/sources.list.d/mono-official-stable.list +RUN apt-get update && apt-get install -y \ mono-devel \ ca-certificates-mono \ nuget \ && apt-get clean -RUN nuget update -self +# Install dotnet SDK +ENV DOTNET_SDK_VERSION 2.1.500 +RUN curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$DOTNET_SDK_VERSION/dotnet-sdk-$DOTNET_SDK_VERSION-linux-x64.tar.gz \ + && mkdir -p /usr/share/dotnet \ + && tar -zxf dotnet.tar.gz -C /usr/share/dotnet \ + && rm dotnet.tar.gz \ + && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet -#================= -# Use cmake 3.6 from jessie-backports -# needed to build grpc_csharp_ext with cmake -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +# Install .NET Core 1.1.10 runtime (required to run netcoreapp1.1) +RUN curl -sSL -o dotnet_old.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/1.1.10/dotnet-debian.9-x64.1.1.10.tar.gz \ + && mkdir -p dotnet_old \ + && tar zxf dotnet_old.tar.gz -C dotnet_old \ + && cp -r dotnet_old/shared/Microsoft.NETCore.App/1.1.10/ /usr/share/dotnet/shared/Microsoft.NETCore.App/ \ + && rm -rf dotnet_old/ dotnet_old.tar.gz +RUN apt-get update && apt-get install -y libunwind8 && apt-get clean -# Install dotnet SDK based on https://www.microsoft.com/net/core#debian -RUN apt-get update && apt-get install -y curl libunwind8 gettext -# dotnet-dev-1.0.0-preview2-003131 -RUN curl -sSL -o dotnet100.tar.gz https://go.microsoft.com/fwlink/?LinkID=827530 -RUN mkdir -p /opt/dotnet && tar zxf dotnet100.tar.gz -C /opt/dotnet -# dotnet-dev-1.0.1 -RUN curl -sSL -o dotnet101.tar.gz https://go.microsoft.com/fwlink/?LinkID=843453 -RUN mkdir -p /opt/dotnet && tar zxf dotnet101.tar.gz -C /opt/dotnet -RUN ln -s /opt/dotnet/dotnet /usr/local/bin # Trigger the population of the local package cache ENV NUGET_XMLDOC_MODE skip diff --git a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile b/tools/dockerfile/test/csharp_stretch_x64/Dockerfile similarity index 56% rename from tools/dockerfile/test/csharp_jessie_x64/Dockerfile rename to tools/dockerfile/test/csharp_stretch_x64/Dockerfile index 030d301a40c..04d25842094 100644 --- a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/csharp_stretch_x64/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2015 gRPC authors. +# Copyright 2018 The gRPC Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM debian:jessie +FROM debian:stretch # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -71,37 +71,36 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t #================ # C# dependencies -# Update to a newer version of mono -RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF -RUN echo "deb http://download.mono-project.com/repo/debian jessie main" | tee /etc/apt/sources.list.d/mono-official.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list +# cmake >=3.6 needed to build grpc_csharp_ext +RUN apt-get update && apt-get install -y cmake && apt-get clean -# Install dependencies -RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \ +# Install mono +RUN apt-get update && apt-get install -y apt-transport-https dirmngr && apt-get clean +RUN apt-key adv --no-tty --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF +RUN echo "deb https://download.mono-project.com/repo/debian stable-stretch main" | tee /etc/apt/sources.list.d/mono-official-stable.list +RUN apt-get update && apt-get install -y \ mono-devel \ ca-certificates-mono \ nuget \ && apt-get clean -RUN nuget update -self +# Install dotnet SDK +ENV DOTNET_SDK_VERSION 2.1.500 +RUN curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$DOTNET_SDK_VERSION/dotnet-sdk-$DOTNET_SDK_VERSION-linux-x64.tar.gz \ + && mkdir -p /usr/share/dotnet \ + && tar -zxf dotnet.tar.gz -C /usr/share/dotnet \ + && rm dotnet.tar.gz \ + && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet -#================= -# Use cmake 3.6 from jessie-backports -# needed to build grpc_csharp_ext with cmake -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +# Install .NET Core 1.1.10 runtime (required to run netcoreapp1.1) +RUN curl -sSL -o dotnet_old.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/1.1.10/dotnet-debian.9-x64.1.1.10.tar.gz \ + && mkdir -p dotnet_old \ + && tar zxf dotnet_old.tar.gz -C dotnet_old \ + && cp -r dotnet_old/shared/Microsoft.NETCore.App/1.1.10/ /usr/share/dotnet/shared/Microsoft.NETCore.App/ \ + && rm -rf dotnet_old/ dotnet_old.tar.gz +RUN apt-get update && apt-get install -y libunwind8 && apt-get clean -# Install dotnet SDK based on https://www.microsoft.com/net/core#debian -RUN apt-get update && apt-get install -y curl libunwind8 gettext -# dotnet-dev-1.0.0-preview2-003131 -RUN curl -sSL -o dotnet100.tar.gz https://go.microsoft.com/fwlink/?LinkID=827530 -RUN mkdir -p /opt/dotnet && tar zxf dotnet100.tar.gz -C /opt/dotnet -# dotnet-dev-1.0.1 -RUN curl -sSL -o dotnet101.tar.gz https://go.microsoft.com/fwlink/?LinkID=843453 -RUN mkdir -p /opt/dotnet && tar zxf dotnet101.tar.gz -C /opt/dotnet -RUN ln -s /opt/dotnet/dotnet /usr/local/bin # Trigger the population of the local package cache ENV NUGET_XMLDOC_MODE skip diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index fbac37e8e75..5c19711ee91 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -777,6 +777,7 @@ doc/environment_variables.md \ doc/fail_fast.md \ doc/fork_support.md \ doc/g_stands_for.md \ +doc/grpc_release_schedule.md \ doc/health-checking.md \ doc/http-grpc-status-mapping.md \ doc/http2-interop-test-descriptions.md \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index f7a9c79620b..72b247c48da 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -777,6 +777,7 @@ doc/environment_variables.md \ doc/fail_fast.md \ doc/fork_support.md \ doc/g_stands_for.md \ +doc/grpc_release_schedule.md \ doc/health-checking.md \ doc/http-grpc-status-mapping.md \ doc/http2-interop-test-descriptions.md \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index b78fb607ad3..8c557383b2e 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -784,6 +784,7 @@ doc/environment_variables.md \ doc/fail_fast.md \ doc/fork_support.md \ doc/g_stands_for.md \ +doc/grpc_release_schedule.md \ doc/health-checking.md \ doc/http-grpc-status-mapping.md \ doc/http2-interop-test-descriptions.md \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index b4f15886c66..0f1943de25f 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -784,6 +784,7 @@ doc/environment_variables.md \ doc/fail_fast.md \ doc/fork_support.md \ doc/g_stands_for.md \ +doc/grpc_release_schedule.md \ doc/health-checking.md \ doc/http-grpc-status-mapping.md \ doc/http2-interop-test-descriptions.md \ diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_rc index 24a3545dedc..eba05449e83 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_macos_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_macos_rc @@ -28,8 +28,7 @@ sudo systemsetup -setusingnetworktime on date # Add GCP credentials for BQ access -# pin google-api-python-client to avoid https://github.com/grpc/grpc/issues/15600 -pip install google-api-python-client==1.6.7 --user python +pip install google-api-python-client oauth2client --user python export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json # If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests @@ -91,3 +90,6 @@ mkdir -p /tmpfs/DerivedData rm -rf ~/Library/Developer/Xcode/DerivedData mkdir -p ~/Library/Developer/Xcode ln -s /tmpfs/DerivedData ~/Library/Developer/Xcode/DerivedData + +# PHP tests currently require using an older version of PHPUnit +ln -sf /usr/local/bin/phpunit-5.7 /usr/local/bin/phpunit diff --git a/tools/remote_build/rbe_common.bazelrc b/tools/remote_build/rbe_common.bazelrc index 75a42a317e8..aa3ddb050cd 100644 --- a/tools/remote_build/rbe_common.bazelrc +++ b/tools/remote_build/rbe_common.bazelrc @@ -18,10 +18,10 @@ startup --host_jvm_args=-Dbazel.DigestFunction=SHA256 -build --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0/bazel_0.16.1/default:toolchain -build --extra_toolchains=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0/bazel_0.16.1/cpp:cc-toolchain-clang-x86_64-default +build --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.16.1/default:toolchain +build --extra_toolchains=//third_party/toolchains:cc-toolchain-clang-x86_64-default # Use custom execution platforms defined in third_party/toolchains -build --extra_execution_platforms=//third_party/toolchains:rbe_ubuntu1604 +build --extra_execution_platforms=//third_party/toolchains:rbe_ubuntu1604,//third_party/toolchains:rbe_ubuntu1604_large build --host_platform=//third_party/toolchains:rbe_ubuntu1604 build --platforms=//third_party/toolchains:rbe_ubuntu1604 @@ -61,9 +61,9 @@ build:msan --cxxopt=--stdlib=libc++ # setting LD_LIBRARY_PATH is necessary # to avoid "libc++.so.1: cannot open shared object file" build:msan --action_env=LD_LIBRARY_PATH=/usr/local/lib -build:msan --host_crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0/bazel_0.16.1/default:toolchain +build:msan --host_crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.16.1/default:toolchain # override the config-agnostic crosstool_top -build:msan --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.0/bazel_0.16.1/msan:toolchain +build:msan --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.16.1/msan:toolchain # thread sanitizer: most settings are already in %workspace%/.bazelrc # we only need a few additional ones that are Foundry specific @@ -71,6 +71,7 @@ build:tsan --copt=-gmlt # TODO(jtattermusch): use more reasonable test timeout build:tsan --test_timeout=3600 build:tsan --test_tag_filters=-qps_json_driver +build:tsan --extra_execution_platforms=//third_party/toolchains:rbe_ubuntu1604,//third_party/toolchains:rbe_ubuntu1604_large # undefined behavior sanitizer: most settings are already in %workspace%/.bazelrc # we only need a few additional ones that are Foundry specific @@ -78,7 +79,7 @@ build:ubsan --copt=-gmlt # TODO(jtattermusch): use more reasonable test timeout build:ubsan --test_timeout=3600 # override the config-agnostic crosstool_top ---crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/experimental/ubuntu16_04_clang/1.0/bazel_0.16.1/ubsan:toolchain +--crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/experimental/ubuntu16_04_clang/1.1/bazel_0.16.1/ubsan:toolchain # TODO(jtattermusch): remove this once Foundry adds the env to the docker image. # ubsan needs symbolizer to work properly, otherwise the suppression file doesn't work # and we get test failures. diff --git a/tools/run_tests/artifacts/build_artifact_python.sh b/tools/run_tests/artifacts/build_artifact_python.sh index 65f2d1c7659..bc6e5582046 100755 --- a/tools/run_tests/artifacts/build_artifact_python.sh +++ b/tools/run_tests/artifacts/build_artifact_python.sh @@ -108,6 +108,11 @@ then ${SETARCH_CMD} "${PYTHON}" src/python/grpcio_testing/setup.py sdist cp -r src/python/grpcio_testing/dist/* "$ARTIFACT_DIR" + # Build grpcio_channelz source distribution + ${SETARCH_CMD} "${PYTHON}" src/python/grpcio_channelz/setup.py \ + preprocess build_package_protos sdist + cp -r src/python/grpcio_channelz/dist/* "$ARTIFACT_DIR" + # Build grpcio_health_checking source distribution ${SETARCH_CMD} "${PYTHON}" src/python/grpcio_health_checking/setup.py \ preprocess build_package_protos sdist diff --git a/tools/run_tests/helper_scripts/build_python.sh b/tools/run_tests/helper_scripts/build_python.sh index 8394f07e518..e43f1fb429c 100755 --- a/tools/run_tests/helper_scripts/build_python.sh +++ b/tools/run_tests/helper_scripts/build_python.sh @@ -189,6 +189,11 @@ pip_install_dir "$ROOT" $VENV_PYTHON "$ROOT/tools/distrib/python/make_grpcio_tools.py" pip_install_dir "$ROOT/tools/distrib/python/grpcio_tools" +# Build/install Channelz +$VENV_PYTHON "$ROOT/src/python/grpcio_channelz/setup.py" preprocess +$VENV_PYTHON "$ROOT/src/python/grpcio_channelz/setup.py" build_package_protos +pip_install_dir "$ROOT/src/python/grpcio_channelz" + # Build/install health checking $VENV_PYTHON "$ROOT/src/python/grpcio_health_checking/setup.py" preprocess $VENV_PYTHON "$ROOT/src/python/grpcio_health_checking/setup.py" build_package_protos diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 021f21dcd42..d026145d66f 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -141,8 +141,8 @@ class CSharpLanguage: class CSharpCoreCLRLanguage: def __init__(self): - self.client_cwd = 'src/csharp/Grpc.IntegrationTesting.Client/bin/Debug/netcoreapp1.0' - self.server_cwd = 'src/csharp/Grpc.IntegrationTesting.Server/bin/Debug/netcoreapp1.0' + self.client_cwd = 'src/csharp/Grpc.IntegrationTesting.Client/bin/Debug/netcoreapp1.1' + self.server_cwd = 'src/csharp/Grpc.IntegrationTesting.Server/bin/Debug/netcoreapp1.1' self.safename = str(self) def client_cmd(self, args): diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index f71be2a65e9..2556e777730 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -942,7 +942,7 @@ class CSharpLanguage(object): self._cmake_arch_option = 'x64' else: _check_compiler(self.args.compiler, ['default', 'coreclr']) - self._docker_distro = 'jessie' + self._docker_distro = 'stretch' def test_specs(self): with open('src/csharp/tests.json') as f: @@ -954,7 +954,7 @@ class CSharpLanguage(object): assembly_extension = '.exe' if self.args.compiler == 'coreclr': - assembly_subdir += '/netcoreapp1.0' + assembly_subdir += '/netcoreapp1.1' runtime_cmd = ['dotnet', 'exec'] assembly_extension = '.dll' else: @@ -1550,16 +1550,9 @@ if args.use_docker: dockerfile_dirs = set([l.dockerfile_dir() for l in languages]) if len(dockerfile_dirs) > 1: - if 'gcov' in args.config: - dockerfile_dir = 'tools/dockerfile/test/multilang_jessie_x64' - print( - 'Using multilang_jessie_x64 docker image for code coverage for ' - 'all languages.') - else: - print( - 'Languages to be tested require running under different docker ' - 'images.') - sys.exit(1) + print('Languages to be tested require running under different docker ' + 'images.') + sys.exit(1) else: dockerfile_dir = next(iter(dockerfile_dirs))