From 8fc3715a17a1b764143d0b37652a07a45d1cdf01 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 18 Dec 2017 14:33:51 -0800 Subject: [PATCH] Catch exceptions from sync method handlers without crashing server --- CMakeLists.txt | 41 +++++ Makefile | 50 +++++- build.yaml | 16 +- .../grpc++/impl/codegen/method_handler_impl.h | 35 +++- test/cpp/end2end/BUILD | 159 ++++++++++-------- test/cpp/end2end/exception_test.cc | 116 +++++++++++++ .../generated/sources_and_headers.json | 19 +++ tools/run_tests/generated/tests.json | 24 +++ 8 files changed, 383 insertions(+), 77 deletions(-) create mode 100644 test/cpp/end2end/exception_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index eed12052685..2cec087850d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -525,6 +525,7 @@ add_dependencies(buildtests_cxx cxx_string_ref_test) add_dependencies(buildtests_cxx cxx_time_test) add_dependencies(buildtests_cxx end2end_test) add_dependencies(buildtests_cxx error_details_test) +add_dependencies(buildtests_cxx exception_test) add_dependencies(buildtests_cxx filter_end2end_test) add_dependencies(buildtests_cxx generic_end2end_test) add_dependencies(buildtests_cxx golden_file_test) @@ -10188,6 +10189,46 @@ target_link_libraries(error_details_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(exception_test + test/cpp/end2end/exception_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(exception_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(exception_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_util + grpc_test_util + grpc++ + grpc + gpr_test_util + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(filter_end2end_test test/cpp/end2end/filter_end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc diff --git a/Makefile b/Makefile index c962a128735..339c52294a6 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,6 @@ CC_opt = $(DEFAULT_CC) CXX_opt = $(DEFAULT_CXX) LD_opt = $(DEFAULT_CC) LDXX_opt = $(DEFAULT_CXX) -CXXFLAGS_opt = -fno-exceptions CPPFLAGS_opt = -O2 DEFINES_opt = NDEBUG @@ -95,7 +94,6 @@ CC_dbg = $(DEFAULT_CC) CXX_dbg = $(DEFAULT_CXX) LD_dbg = $(DEFAULT_CC) LDXX_dbg = $(DEFAULT_CXX) -CXXFLAGS_dbg = -fno-exceptions CPPFLAGS_dbg = -O0 DEFINES_dbg = _DEBUG DEBUG @@ -1126,6 +1124,7 @@ cxx_string_ref_test: $(BINDIR)/$(CONFIG)/cxx_string_ref_test cxx_time_test: $(BINDIR)/$(CONFIG)/cxx_time_test end2end_test: $(BINDIR)/$(CONFIG)/end2end_test error_details_test: $(BINDIR)/$(CONFIG)/error_details_test +exception_test: $(BINDIR)/$(CONFIG)/exception_test filter_end2end_test: $(BINDIR)/$(CONFIG)/filter_end2end_test generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test golden_file_test: $(BINDIR)/$(CONFIG)/golden_file_test @@ -1573,6 +1572,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/cxx_time_test \ $(BINDIR)/$(CONFIG)/end2end_test \ $(BINDIR)/$(CONFIG)/error_details_test \ + $(BINDIR)/$(CONFIG)/exception_test \ $(BINDIR)/$(CONFIG)/filter_end2end_test \ $(BINDIR)/$(CONFIG)/generic_end2end_test \ $(BINDIR)/$(CONFIG)/golden_file_test \ @@ -1702,6 +1702,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/cxx_time_test \ $(BINDIR)/$(CONFIG)/end2end_test \ $(BINDIR)/$(CONFIG)/error_details_test \ + $(BINDIR)/$(CONFIG)/exception_test \ $(BINDIR)/$(CONFIG)/filter_end2end_test \ $(BINDIR)/$(CONFIG)/generic_end2end_test \ $(BINDIR)/$(CONFIG)/golden_file_test \ @@ -2101,6 +2102,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/end2end_test || ( echo test end2end_test failed ; exit 1 ) $(E) "[RUN] Testing error_details_test" $(Q) $(BINDIR)/$(CONFIG)/error_details_test || ( echo test error_details_test failed ; exit 1 ) + $(E) "[RUN] Testing exception_test" + $(Q) $(BINDIR)/$(CONFIG)/exception_test || ( echo test exception_test failed ; exit 1 ) $(E) "[RUN] Testing filter_end2end_test" $(Q) $(BINDIR)/$(CONFIG)/filter_end2end_test || ( echo test filter_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing generic_end2end_test" @@ -14981,6 +14984,49 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/util/error_details_test.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc +EXCEPTION_TEST_SRC = \ + test/cpp/end2end/exception_test.cc \ + +EXCEPTION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(EXCEPTION_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/exception_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/exception_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/exception_test: $(PROTOBUF_DEP) $(EXCEPTION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(EXCEPTION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/exception_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/end2end/exception_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_exception_test: $(EXCEPTION_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(EXCEPTION_TEST_OBJS:.o=.dep) +endif +endif + + FILTER_END2END_TEST_SRC = \ test/cpp/end2end/filter_end2end_test.cc \ diff --git a/build.yaml b/build.yaml index 42d72459811..8ab15b77414 100644 --- a/build.yaml +++ b/build.yaml @@ -4007,6 +4007,20 @@ targets: deps: - grpc++_error_details - grpc++ +- name: exception_test + gtest: true + build: test + language: c++ + src: + - test/cpp/end2end/exception_test.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - gpr_test_util + - gpr + uses_polling: false - name: filter_end2end_test gtest: true build: test @@ -4913,7 +4927,6 @@ configs: DEFINES: NDEBUG dbg: CPPFLAGS: -O0 - CXXFLAGS: -fno-exceptions DEFINES: _DEBUG DEBUG gcov: CC: gcc @@ -4956,7 +4969,6 @@ configs: LDFLAGS: -rdynamic opt: CPPFLAGS: -O2 - CXXFLAGS: -fno-exceptions DEFINES: NDEBUG stapprof: CPPFLAGS: -O2 -DGRPC_STAP_PROFILER diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index c0af4ca1307..b72dceb1b4c 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -27,6 +27,25 @@ namespace grpc { namespace internal { + +// Invoke the method handler, fill in the status, and +// return whether or not we finished safely (without an exception). +// Note that exception handling is 0-cost in most compiler/library +// implementations (except when an exception is actually thrown), +// so this process doesn't require additional overhead in the common case. +// Additionally, we don't need to return if we caught an exception or not; +// the handling is the same in either case. +template +Status CatchingFunctionHandler(F&& callable) { + try { + return callable(); + } catch (const std::exception& e) { + return Status(StatusCode::UNKNOWN, e.what()); + } catch (...) { + return Status(StatusCode::UNKNOWN, "Exception in method handler"); + } +} + /// A wrapper class of an application provided rpc method handler. template class RpcMethodHandler : public MethodHandler { @@ -43,7 +62,9 @@ class RpcMethodHandler : public MethodHandler { param.request.bbuf_ptr(), &req); ResponseType rsp; if (status.ok()) { - status = func_(service_, param.server_context, &req, &rsp); + status = CatchingFunctionHandler([this, ¶m, &req, &rsp] { + return func_(service_, param.server_context, &req, &rsp); + }); } GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_); @@ -86,7 +107,9 @@ class ClientStreamingHandler : public MethodHandler { void RunHandler(const HandlerParameter& param) final { ServerReader reader(param.call, param.server_context); ResponseType rsp; - Status status = func_(service_, param.server_context, &reader, &rsp); + Status status = CatchingFunctionHandler([this, ¶m, &reader, &rsp] { + return func_(service_, param.server_context, &reader, &rsp); + }); GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_); CallOpSet writer(param.call, param.server_context); - status = func_(service_, param.server_context, &req, &writer); + status = CatchingFunctionHandler([this, ¶m, &req, &writer] { + return func_(service_, param.server_context, &req, &writer); + }); } CallOpSet ops; @@ -172,7 +197,9 @@ class TemplatedBidiStreamingHandler : public MethodHandler { void RunHandler(const HandlerParameter& param) final { Streamer stream(param.call, param.server_context); - Status status = func_(param.server_context, &stream); + Status status = CatchingFunctionHandler([this, ¶m, &stream] { + return func_(param.server_context, &stream); + }); CallOpSet ops; if (!param.server_context->sent_initial_metadata_) { diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index fa77c30aca6..8894c68b95d 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -16,25 +16,31 @@ licenses(["notice"]) # Apache v2 load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package", "grpc_cc_binary") -grpc_package(name = "test/cpp/end2end", visibility = "public") # Allows external users to implement end2end tests. +grpc_package( + name = "test/cpp/end2end", + visibility = "public", +) # Allows external users to implement end2end tests. grpc_cc_library( name = "test_service_impl", testonly = True, srcs = ["test_service_impl.cc"], hdrs = ["test_service_impl.h"], + external_deps = [ + "gtest", + ], deps = [ "//src/proto/grpc/testing:echo_proto", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "async_end2end_test", srcs = ["async_end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -47,14 +53,17 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "client_crash_test", srcs = ["client_crash_test.cc"], + data = [ + ":client_crash_test_server", + ], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -66,18 +75,16 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - data = [ - ":client_crash_test_server", - ], - external_deps = [ - "gtest", - ], ) grpc_cc_binary( name = "client_crash_test_server", testonly = True, srcs = ["client_crash_test_server.cc"], + external_deps = [ + "gflags", + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -89,16 +96,15 @@ grpc_cc_binary( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gflags", - "gtest", - ], ) grpc_cc_library( name = "end2end_test_lib", - srcs = ["end2end_test.cc"], testonly = True, + srcs = ["end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", @@ -111,40 +117,58 @@ grpc_cc_library( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "end2end_test", deps = [ - ":end2end_test_lib" + ":end2end_test_lib", ], ) grpc_cc_test( - name = "filter_end2end_test", - srcs = ["filter_end2end_test.cc"], + name = "exception_test", + srcs = ["exception_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", "//:grpc++", "//src/proto/grpc/testing:echo_messages_proto", "//src/proto/grpc/testing:echo_proto", - "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", "//test/core/util:gpr_test_util", "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], +) + +grpc_cc_test( + name = "filter_end2end_test", + srcs = ["filter_end2end_test.cc"], external_deps = [ "gtest", ], + deps = [ + "//:gpr", + "//:grpc", + "//:grpc++", + "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], ) grpc_cc_test( name = "generic_end2end_test", srcs = ["generic_end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -156,14 +180,14 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "hybrid_end2end_test", srcs = ["hybrid_end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", @@ -176,14 +200,15 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "mock_test", srcs = ["mock_test.cc"], + external_deps = [ + "gmock", + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -196,15 +221,14 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gmock", - "gtest", - ], ) grpc_cc_test( name = "client_lb_end2end_test", srcs = ["client_lb_end2end_test.cc"], + external_deps = [ + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", @@ -217,37 +241,38 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "grpclb_end2end_test", srcs = ["grpclb_end2end_test.cc"], + external_deps = [ + "gmock", + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", "//:grpc", "//:grpc++", + "//:grpc_resolver_fake", "//src/proto/grpc/lb/v1:load_balancer_proto", "//src/proto/grpc/testing:echo_messages_proto", "//src/proto/grpc/testing:echo_proto", "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", - "//:grpc_resolver_fake", "//test/core/util:gpr_test_util", "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gmock", - "gtest", - ], ) grpc_cc_test( name = "proto_server_reflection_test", srcs = ["proto_server_reflection_test.cc"], + external_deps = [ + "gtest", + "gflags", + ], deps = [ ":test_service_impl", "//:gpr", @@ -262,15 +287,14 @@ grpc_cc_test( "//test/cpp/util:grpc++_proto_reflection_desc_db", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - "gflags", - ], ) grpc_cc_test( name = "server_builder_plugin_test", srcs = ["server_builder_plugin_test.cc"], + external_deps = [ + "gtest", + ], deps = [ ":test_service_impl", "//:gpr", @@ -283,14 +307,17 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "server_crash_test", srcs = ["server_crash_test.cc"], + data = [ + ":server_crash_test_client", + ], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -302,18 +329,16 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], - data = [ - ":server_crash_test_client", - ], ) grpc_cc_binary( name = "server_crash_test_client", testonly = True, srcs = ["server_crash_test_client.cc"], + external_deps = [ + "gflags", + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -325,15 +350,14 @@ grpc_cc_binary( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gflags", - "gtest", - ], ) grpc_cc_test( name = "shutdown_test", srcs = ["shutdown_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -345,14 +369,14 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "streaming_throughput_test", srcs = ["streaming_throughput_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -364,14 +388,14 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) grpc_cc_test( name = "thread_stress_test", srcs = ["thread_stress_test.cc"], + external_deps = [ + "gtest", + ], deps = [ "//:gpr", "//:grpc", @@ -383,7 +407,4 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], - external_deps = [ - "gtest", - ], ) diff --git a/test/cpp/end2end/exception_test.cc b/test/cpp/end2end/exception_test.cc new file mode 100644 index 00000000000..6545ffa5304 --- /dev/null +++ b/test/cpp/end2end/exception_test.cc @@ -0,0 +1,116 @@ +/* + * + * Copyright 2017 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. + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/test_config.h" + +#include + +namespace grpc { +namespace testing { + +const char* kErrorMessage = "This service caused an exception"; + +class ExceptingServiceImpl : public ::grpc::testing::EchoTestService::Service { + public: + Status Echo(ServerContext* server_context, const EchoRequest* request, + EchoResponse* response) override { + throw - 1; + } + Status RequestStream(ServerContext* context, + ServerReader* reader, + EchoResponse* response) override { + throw ServiceException(); + } + + private: + class ServiceException final : public std::exception { + public: + ServiceException() {} + + private: + const char* what() const noexcept override { return kErrorMessage; } + }; +}; + +class ExceptionTest : public ::testing::Test { + protected: + ExceptionTest() {} + + void SetUp() override { + ServerBuilder builder; + builder.RegisterService(&service_); + server_ = builder.BuildAndStart(); + } + + void TearDown() override { server_->Shutdown(); } + + void ResetStub() { + channel_ = server_->InProcessChannel(ChannelArguments()); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + std::shared_ptr channel_; + std::unique_ptr stub_; + std::unique_ptr server_; + ExceptingServiceImpl service_; +}; + +TEST_F(ExceptionTest, Unary) { + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("test"); + ClientContext context; + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNKNOWN); +} + +TEST_F(ExceptionTest, RequestStream) { + ResetStub(); + EchoResponse response; + ClientContext context; + + auto stream = stub_->RequestStream(&context, &response); + stream->WritesDone(); + Status s = stream->Finish(); + + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNKNOWN); + EXPECT_EQ(s.error_message(), kErrorMessage); +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index d432bd0e537..137e36a432e 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -3160,6 +3160,25 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc++", + "grpc++_test_util", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "exception_test", + "src": [ + "test/cpp/end2end/exception_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 98517cba2e7..bb672bea7da 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3695,6 +3695,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "exception_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": false + }, { "args": [], "benchmark": false,