Skip to content

Commit 737c58a

Browse files
author
aabagdasaryan
committed
feat grpc: support mocked errors in testsuite
commit_hash:74e00cd226218dd6297f99429abd530820d0a0c0
1 parent caf37e4 commit 737c58a

File tree

19 files changed

+414
-12
lines changed

19 files changed

+414
-12
lines changed

.mapping.json

+11
Original file line numberDiff line numberDiff line change
@@ -1904,6 +1904,14 @@
19041904
"grpc/functional_tests/metrics/tests/conftest.py":"taxi/uservices/userver/grpc/functional_tests/metrics/tests/conftest.py",
19051905
"grpc/functional_tests/metrics/tests/static/metrics_values.txt":"taxi/uservices/userver/grpc/functional_tests/metrics/tests/static/metrics_values.txt",
19061906
"grpc/functional_tests/metrics/tests/test_metrics.py":"taxi/uservices/userver/grpc/functional_tests/metrics/tests/test_metrics.py",
1907+
"grpc/functional_tests/middleware_client/CMakeLists.txt":"taxi/uservices/userver/grpc/functional_tests/middleware_client/CMakeLists.txt",
1908+
"grpc/functional_tests/middleware_client/config_vars.yaml":"taxi/uservices/userver/grpc/functional_tests/middleware_client/config_vars.yaml",
1909+
"grpc/functional_tests/middleware_client/main.cpp":"taxi/uservices/userver/grpc/functional_tests/middleware_client/main.cpp",
1910+
"grpc/functional_tests/middleware_client/proto/samples/greeter.proto":"taxi/uservices/userver/grpc/functional_tests/middleware_client/proto/samples/greeter.proto",
1911+
"grpc/functional_tests/middleware_client/src/greeter_service.hpp":"taxi/uservices/userver/grpc/functional_tests/middleware_client/src/greeter_service.hpp",
1912+
"grpc/functional_tests/middleware_client/static_config.yaml":"taxi/uservices/userver/grpc/functional_tests/middleware_client/static_config.yaml",
1913+
"grpc/functional_tests/middleware_client/tests/conftest.py":"taxi/uservices/userver/grpc/functional_tests/middleware_client/tests/conftest.py",
1914+
"grpc/functional_tests/middleware_client/tests/test_mocked_fail.py":"taxi/uservices/userver/grpc/functional_tests/middleware_client/tests/test_mocked_fail.py",
19071915
"grpc/functional_tests/middleware_server/CMakeLists.txt":"taxi/uservices/userver/grpc/functional_tests/middleware_server/CMakeLists.txt",
19081916
"grpc/functional_tests/middleware_server/config_vars.yaml":"taxi/uservices/userver/grpc/functional_tests/middleware_server/config_vars.yaml",
19091917
"grpc/functional_tests/middleware_server/proto/samples/greeter.proto":"taxi/uservices/userver/grpc/functional_tests/middleware_server/proto/samples/greeter.proto",
@@ -1962,6 +1970,8 @@
19621970
"grpc/include/userver/ugrpc/client/middlewares/deadline_propagation/middleware.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/middlewares/deadline_propagation/middleware.hpp",
19631971
"grpc/include/userver/ugrpc/client/middlewares/fwd.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/middlewares/fwd.hpp",
19641972
"grpc/include/userver/ugrpc/client/middlewares/log/component.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/middlewares/log/component.hpp",
1973+
"grpc/include/userver/ugrpc/client/middlewares/testsuite/component.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/middlewares/testsuite/component.hpp",
1974+
"grpc/include/userver/ugrpc/client/middlewares/testsuite/middleware.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/middlewares/testsuite/middleware.hpp",
19651975
"grpc/include/userver/ugrpc/client/qos.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/qos.hpp",
19661976
"grpc/include/userver/ugrpc/client/response_future.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/response_future.hpp",
19671977
"grpc/include/userver/ugrpc/client/rpc.hpp":"taxi/uservices/userver/grpc/include/userver/ugrpc/client/rpc.hpp",
@@ -2063,6 +2073,7 @@
20632073
"grpc/src/ugrpc/client/middlewares/log/component.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/middlewares/log/component.cpp",
20642074
"grpc/src/ugrpc/client/middlewares/log/middleware.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/middlewares/log/middleware.cpp",
20652075
"grpc/src/ugrpc/client/middlewares/log/middleware.hpp":"taxi/uservices/userver/grpc/src/ugrpc/client/middlewares/log/middleware.hpp",
2076+
"grpc/src/ugrpc/client/middlewares/testsuite/middleware.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/middlewares/testsuite/middleware.cpp",
20662077
"grpc/src/ugrpc/client/qos.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/qos.cpp",
20672078
"grpc/src/ugrpc/client/rpc.cpp":"taxi/uservices/userver/grpc/src/ugrpc/client/rpc.cpp",
20682079
"grpc/src/ugrpc/client/secdist.hpp":"taxi/uservices/userver/grpc/src/ugrpc/client/secdist.hpp",

core/include/userver/middlewares/groups.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ struct Core final {
5353
};
5454

5555
/// @brief The group is located after `Core`.
56+
///
57+
/// @details There are:
58+
///
59+
/// gRPC-client:
60+
/// * ugrpc::client::middlewares::testsuite::Component
5661
struct PostCore final {
5762
static constexpr std::string_view kName = "post-core";
5863
static inline const auto kDependency = middlewares::MiddlewareDependencyBuilder().After<Core>();

grpc/functional_tests/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-basic-server)
1313

1414
add_subdirectory(middleware_server)
1515
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-middleware-server)
16+
17+
add_subdirectory(middleware_client)
18+
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-middleware-client)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
project(userver-grpc-tests-middleware-client CXX)
2+
3+
add_executable(${PROJECT_NAME} main.cpp)
4+
5+
target_include_directories(${PROJECT_NAME} PRIVATE src)
6+
7+
userver_add_grpc_library(${PROJECT_NAME}-proto PROTOS samples/greeter.proto)
8+
target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}-proto)
9+
10+
userver_chaos_testsuite_add(
11+
TESTS_DIRECTORY tests
12+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# yaml
2+
logger-level: info
3+
4+
config-server-url: http://localhost:8083/
5+
server-port: 8185
6+
monitor-server-port: 8186
7+
8+
greeter-client-endpoint: $grpc_mockserver
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <fmt/format.h>
2+
3+
#include <userver/components/minimal_server_component_list.hpp>
4+
#include <userver/congestion_control/component.hpp>
5+
#include <userver/server/handlers/server_monitor.hpp>
6+
#include <userver/testsuite/testsuite_support.hpp>
7+
#include <userver/utest/using_namespace_userver.hpp>
8+
#include <userver/utils/daemon_run.hpp>
9+
10+
#include <userver/ugrpc/client/client_factory_component.hpp>
11+
#include <userver/ugrpc/client/component_list.hpp>
12+
#include <userver/ugrpc/server/component_list.hpp>
13+
14+
#include <greeter_service.hpp>
15+
16+
int main(int argc, const char* const argv[]) {
17+
const auto component_list = components::MinimalServerComponentList()
18+
.Append<server::handlers::ServerMonitor>()
19+
.Append<congestion_control::Component>()
20+
.Append<components::TestsuiteSupport>()
21+
.AppendComponentList(ugrpc::server::DefaultComponentList())
22+
.AppendComponentList(ugrpc::client::DefaultComponentList())
23+
.Append<ugrpc::client::ClientFactoryComponent>()
24+
.Append<functional_tests::ClientComponent>("greeter-client")
25+
.Append<functional_tests::GreeterServiceComponent>();
26+
27+
return utils::DaemonMain(argc, argv, component_list);
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
syntax = "proto3";
2+
3+
package samples.api;
4+
5+
service GreeterService {
6+
rpc SayHello(GreetingRequest) returns(GreetingResponse) {}
7+
}
8+
9+
message GreetingRequest {
10+
string name = 1;
11+
}
12+
13+
message GreetingResponse {
14+
string greeting = 1;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#pragma once
2+
3+
#include <userver/components/component.hpp>
4+
#include <userver/utest/using_namespace_userver.hpp>
5+
#include <userver/yaml_config/merge_schemas.hpp>
6+
7+
#include <userver/ugrpc/client/client_factory_component.hpp>
8+
#include <userver/ugrpc/client/exceptions.hpp>
9+
#include <userver/ugrpc/client/simple_client_component.hpp>
10+
11+
#include <samples/greeter_client.usrv.pb.hpp>
12+
#include <samples/greeter_service.usrv.pb.hpp>
13+
14+
namespace functional_tests {
15+
16+
using Client = samples::api::GreeterServiceClient;
17+
using ClientComponent = ugrpc::client::SimpleClientComponent<Client>;
18+
19+
class GreeterServiceComponent final : public samples::api::GreeterServiceBase::Component {
20+
public:
21+
static constexpr std::string_view kName = "greeter-service";
22+
23+
GreeterServiceComponent(const components::ComponentConfig& config, const components::ComponentContext& context)
24+
: samples::api::GreeterServiceBase::Component(config, context),
25+
client_factory_(context.FindComponent<ugrpc::client::ClientFactoryComponent>().GetFactory()),
26+
client_(context.FindComponent<ClientComponent>("greeter-client").GetClient()) {}
27+
28+
SayHelloResult SayHello(CallContext& context, samples::api::GreetingRequest&& request) override;
29+
30+
static yaml_config::Schema GetStaticConfigSchema();
31+
32+
private:
33+
ugrpc::client::ClientFactory& client_factory_;
34+
Client& client_;
35+
};
36+
37+
inline GreeterServiceComponent::SayHelloResult
38+
GreeterServiceComponent::SayHello(CallContext& /*context*/, samples::api::GreetingRequest&& request) {
39+
samples::api::GreetingResponse response;
40+
auto context = std::make_unique<grpc::ClientContext>();
41+
try {
42+
response.set_greeting(client_.SayHello(request, std::move(context)).greeting());
43+
} catch (const ugrpc::client::RpcInterruptedError& e) {
44+
response.set_greeting(fmt::format("Client caught mocked error: {}", e.what()));
45+
}
46+
47+
return response;
48+
}
49+
50+
inline yaml_config::Schema GreeterServiceComponent::GetStaticConfigSchema() {
51+
return yaml_config::MergeSchemas<ugrpc::server::ServiceComponentBase>(R"(
52+
type: object
53+
description: gRPC sample greater service component
54+
additionalProperties: false
55+
properties: {}
56+
)");
57+
}
58+
59+
} // namespace functional_tests
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# yaml
2+
components_manager:
3+
components:
4+
# The required common components
5+
logging:
6+
fs-task-processor: fs-task-processor
7+
loggers:
8+
default:
9+
file_path: '@stderr'
10+
level: debug
11+
overflow_behavior: discard
12+
13+
handler-server-monitor:
14+
path: /service/monitor
15+
method: GET
16+
task_processor: main-task-processor
17+
18+
19+
# gRPC server and service
20+
grpc-server:
21+
port: 8091
22+
23+
congestion-control:
24+
25+
grpc-server-logging:
26+
msg-size-log-limit: 10
27+
28+
grpc-server-middlewares-pipeline:
29+
30+
greeter-service:
31+
task-processor: main-task-processor
32+
disable-all-pipeline-middlewares: true
33+
middlewares:
34+
grpc-server-logging:
35+
enabled: true
36+
grpc-server-baggage:
37+
enabled: true
38+
39+
# gRPC client
40+
grpc-client-common:
41+
blocking-task-processor: grpc-blocking-task-processor
42+
43+
grpc-client-factory:
44+
middlewares:
45+
grpc-client-deadline-propagation:
46+
enabled: false
47+
channel-args: {}
48+
49+
greeter-client:
50+
endpoint: $greeter-client-endpoint
51+
52+
# http server
53+
server:
54+
listener:
55+
port: 8092
56+
task_processor: main-task-processor
57+
listener-monitor:
58+
port: $monitor-server-port
59+
port#fallback: 8086
60+
connection:
61+
in_buffer_size: 32768
62+
requests_queue_size_threshold: 100
63+
task_processor: main-task-processor
64+
65+
testsuite-support:
66+
grpc-client-logging:
67+
grpc-client-deadline-propagation:
68+
grpc-client-baggage:
69+
70+
default_task_processor: main-task-processor
71+
72+
task_processors:
73+
grpc-blocking-task-processor: # For blocking gRPC channel creation
74+
thread_name: grpc-worker
75+
worker_threads: 2
76+
main-task-processor: # For non-blocking operations
77+
worker_threads: 4
78+
fs-task-processor: # For blocking filesystem operations
79+
worker_threads: 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import pytest
2+
3+
import samples.greeter_pb2_grpc as greeter_services
4+
5+
pytest_plugins = ['pytest_userver.plugins.grpc']
6+
7+
8+
@pytest.fixture
9+
def grpc_client(grpc_channel):
10+
return greeter_services.GreeterServiceStub(grpc_channel)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import pytest_userver.grpc
2+
3+
import samples.greeter_pb2 as greeter_protos
4+
import samples.greeter_pb2_grpc as greeter_services
5+
6+
7+
# /// [Mocked network failure]
8+
async def test_network_fail(grpc_client, grpc_mockserver_new):
9+
@grpc_mockserver_new(greeter_services.GreeterServiceServicer.SayHello)
10+
async def mock_say_hello(request, context):
11+
raise pytest_userver.grpc.NetworkError()
12+
13+
request = greeter_protos.GreetingRequest(name='No matter')
14+
response = await grpc_client.SayHello(request)
15+
assert (
16+
response.greeting
17+
== "Client caught mocked error: 'samples.api.GreeterService/SayHello' failed: interrupted at Testsuite network"
18+
)
19+
# /// [Mocked network failure]
20+
21+
22+
# /// [Mocked timeout failure]
23+
async def test_timeout_fail(grpc_client, grpc_mockserver_new):
24+
@grpc_mockserver_new(greeter_services.GreeterServiceServicer.SayHello)
25+
async def mock_say_hello(request, context):
26+
raise pytest_userver.grpc.TimeoutError()
27+
28+
request = greeter_protos.GreetingRequest(name='No matter')
29+
response = await grpc_client.SayHello(request)
30+
assert (
31+
response.greeting
32+
== "Client caught mocked error: 'samples.api.GreeterService/SayHello' failed: interrupted at Testsuite timeout"
33+
)
34+
# /// [Mocked timeout failure]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
/// @file userver/ugrpc/client/middlewares/testsuite/component.hpp
4+
/// @brief @copybrief ugrpc::client::middlewares::testsuite::Component
5+
6+
#include <userver/ugrpc/client/middlewares/base.hpp>
7+
#include <userver/ugrpc/client/middlewares/testsuite/middleware.hpp>
8+
9+
USERVER_NAMESPACE_BEGIN
10+
11+
namespace ugrpc::client::middlewares::testsuite {
12+
13+
// clang-format off
14+
15+
/// @ingroup userver_components
16+
///
17+
/// @brief Component for gRPC client testsuite support
18+
/// The component supports testsuite errors thrown from the mockserver, such as `NetworkError`, `TimeoutError`.
19+
/// @see @ref pytest_userver.plugins.grpc.mockserver.grpc_mockserver_new "grpc_mockserver_new"
20+
/// @see @ref pytest_userver.grpc.TimeoutError
21+
/// @see @ref pytest_userver.grpc.NetworkError
22+
///
23+
/// The component does **not** have any options for service config.
24+
25+
// clang-format on
26+
27+
using Component = SimpleMiddlewareFactoryComponent<Middleware>;
28+
29+
} // namespace ugrpc::client::middlewares::testsuite
30+
31+
template <>
32+
inline constexpr auto components::kConfigFileMode<ugrpc::client::middlewares::testsuite::Component> =
33+
ConfigFileMode::kNotRequired;
34+
35+
USERVER_NAMESPACE_END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
3+
/// @file userver/ugrpc/client/middlewares/testsuite/middleware.hpp
4+
/// @brief @copybrief ugrpc::client::middlewares::testsuite::Middleware
5+
6+
#include <userver/middlewares/groups.hpp>
7+
#include <userver/ugrpc/client/middlewares/base.hpp>
8+
9+
USERVER_NAMESPACE_BEGIN
10+
11+
namespace ugrpc::client::middlewares::testsuite {
12+
13+
/// @brief middleware for gRPC client testsuite
14+
class Middleware final : public MiddlewareBase {
15+
public:
16+
/// @ingroup userver_component_names
17+
/// @brief The default name of
18+
/// ugrpc::client::middlewares::testsuite::Component.
19+
static constexpr std::string_view kName = "grpc-client-middleware-testsuite";
20+
21+
/// @brief dependency of this middleware. PostCore group.
22+
static inline const auto kDependency = USERVER_NAMESPACE::middlewares::MiddlewareDependencyBuilder()
23+
.InGroup<USERVER_NAMESPACE::middlewares::groups::PostCore>();
24+
25+
Middleware() = default;
26+
27+
void PostFinish(MiddlewareCallContext&, const grpc::Status&) const override;
28+
};
29+
30+
} // namespace ugrpc::client::middlewares::testsuite
31+
32+
USERVER_NAMESPACE_END

grpc/src/ugrpc/client/component_list.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <userver/ugrpc/client/middlewares/base.hpp>
66
#include <userver/ugrpc/client/middlewares/deadline_propagation/component.hpp>
77
#include <userver/ugrpc/client/middlewares/log/component.hpp>
8+
#include <userver/ugrpc/client/middlewares/testsuite/component.hpp>
89

910
USERVER_NAMESPACE_BEGIN
1011

@@ -15,7 +16,8 @@ components::ComponentList MinimalComponentList() {
1516
.Append<CommonComponent>()
1617
.Append<MiddlewarePipelineComponent>()
1718
.Append<middlewares::deadline_propagation::Component>()
18-
.Append<middlewares::log::Component>();
19+
.Append<middlewares::log::Component>()
20+
.Append<middlewares::testsuite::Component>();
1921
}
2022

2123
components::ComponentList DefaultComponentList() {

0 commit comments

Comments
 (0)