userver: /home/antonyzhilin/arcadia/taxi/uservices/userver/libraries/grpc-protovalidate/tests/validator_client_test.cpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
validator_client_test.cpp
1#include <userver/utest/utest.hpp>
2
3#include <buf/validate/validate.pb.h>
4
5#include <userver/engine/async.hpp>
6#include <userver/grpc-protovalidate/client/exceptions.hpp>
7#include <userver/ugrpc/client/exceptions.hpp>
8#include <userver/ugrpc/tests/service_fixtures.hpp>
9
10#include <types/unit_test_client.usrv.pb.hpp>
11#include <types/unit_test_service.usrv.pb.hpp>
12
13#include <grpc-protovalidate/client/middleware.hpp>
14#include "utils.hpp"
15
16USERVER_NAMESPACE_BEGIN
17
18namespace {
19
20types::ConstrainedResponse CreateResponse(int32_t request_id) {
21 types::ConstrainedResponse response;
22
23 if (request_id != 0) {
24 // happy path
25 response.set_field(request_id);
26
27 types::ConstrainedMessage msg;
28 msg.set_required_rule(5);
29 *response.add_messages() = std::move(msg);
30 *response.add_messages() = tests::CreateValidMessage(6);
31 } else {
32 // error path
33 response.set_field(100);
34 *response.add_messages() = types::ConstrainedMessage{};
35 *response.add_messages() = tests::CreateInvalidMessage();
36 }
37
38 return response;
39}
40
41class UnitTestServiceValidator final : public types::UnitTestServiceBase {
42public:
43 CheckConstraintsUnaryResult CheckConstraintsUnary(CallContext&, types::ConstrainedRequest&& request) override {
44 return CreateResponse(request.field());
45 }
46
47 CheckConstraintsStreamingResult
48 CheckConstraintsStreaming(CallContext&, CheckConstraintsStreamingReaderWriter& stream) override {
49 types::ConstrainedRequest request;
50 while (stream.Read(request)) {
51 stream.Write(CreateResponse(request.field()));
52 }
53 return grpc::Status::OK;
54 }
55
56 CheckInvalidResponseConstraintsResult CheckInvalidResponseConstraints(CallContext&, google::protobuf::Empty&&)
57 override {
58 types::InvalidConstraints response;
59 response.set_field(1);
60 return response;
61 }
62};
63
64class GrpcClientValidatorTest : public ugrpc::tests::ServiceFixtureBase,
65 public testing::WithParamInterface<grpc_protovalidate::client::Settings> {
66public:
67 GrpcClientValidatorTest() {
68 SetClientMiddlewares({std::make_shared<grpc_protovalidate::client::Middleware>(GetParam())});
69 RegisterService(service_);
70 StartServer();
71 }
72
73 ~GrpcClientValidatorTest() override { StopServer(); }
74
75private:
76 UnitTestServiceValidator service_;
77};
78
79} // namespace
80
81INSTANTIATE_UTEST_SUITE_P(
82 /*no prefix*/,
83 GrpcClientValidatorTest,
84 testing::Values(
85 grpc_protovalidate::client::Settings{
86 .per_method =
87 {
88 {"types.UnitTestService/CheckConstraintsUnary", {.fail_fast = false}},
89 {"/UnknownMethod", {.fail_fast = true}},
90 }},
91 grpc_protovalidate::client::Settings{
92 .global =
93 {
94 .fail_fast = false,
95 },
96 .per_method =
97 {
98 {"types.UnitTestService/CheckConstraintsUnary", {.fail_fast = false}},
99 {"/UnknownMethod", {.fail_fast = true}},
100 }}
101 )
102);
103
104UTEST_P_MT(GrpcClientValidatorTest, AllValid, 2) {
105 constexpr std::size_t kRequestCount = 3;
106 auto client = MakeClient<types::UnitTestServiceClient>();
107 auto stream = client.CheckConstraintsStreaming();
108
109 types::ConstrainedRequest request;
110 std::vector<types::ConstrainedRequest> requests(kRequestCount);
111 std::vector<types::ConstrainedResponse> responses;
112
113 for (std::size_t i = 0; i < kRequestCount; ++i) {
114 requests[i].set_field(static_cast<int32_t>(i + 1));
115 }
116
117 // check unary method
118
119 types::ConstrainedResponse response;
120 UEXPECT_NO_THROW(response = client.CheckConstraintsUnary(requests[0]));
121 EXPECT_EQ(response.field(), requests[0].field());
122
123 // check streaming method
124
125 auto write_task = engine::AsyncNoSpan([&stream, &requests] {
126 for (const auto& request : requests) {
127 const bool success = stream.Write(request);
128 if (!success) return false;
129 }
130
131 return stream.WritesDone();
132 });
133
134 while (stream.Read(response)) {
135 responses.push_back(std::move(response));
136 }
137
138 ASSERT_TRUE(write_task.Get());
139 ASSERT_EQ(responses.size(), kRequestCount);
140
141 for (std::size_t i = 0; i < kRequestCount; ++i) {
142 EXPECT_EQ(responses[i].field(), requests[i].field());
143 }
144}
145
146UTEST_P_MT(GrpcClientValidatorTest, AllInvalid, 2) {
147 constexpr std::size_t kRequestCount = 3;
148 const auto& streaming_settings = GetParam().Get("types.UnitTestService/CheckConstraintsStreaming");
149 auto client = MakeClient<types::UnitTestServiceClient>();
150 auto stream = client.CheckConstraintsStreaming();
151
152 types::ConstrainedRequest request;
153 std::vector<types::ConstrainedRequest> requests(kRequestCount);
154 std::vector<types::ConstrainedResponse> responses;
155
156 request.set_field(1);
157 requests[0] = request;
158 request.set_field(0);
159 requests[1] = request;
160 request.set_field(3);
161 requests[2] = request;
162
163 // check unary method
164
165 try {
166 [[maybe_unused]] auto response = client.CheckConstraintsUnary(requests[1]);
167 ADD_FAILURE() << "Call must fail";
168 } catch (const grpc_protovalidate::client::ResponseError& err) {
169 EXPECT_EQ(err.GetErrorInfo().violations_size(), 20);
170 } catch (...) {
171 ADD_FAILURE() << "'ResponseError' exception expected";
172 }
173
174 // check streaming method
175
176 auto write_task = engine::AsyncNoSpan([&stream, &requests] {
177 for (const auto& request : requests) {
178 const bool success = stream.Write(request);
179 if (!success) return false;
180 }
181
182 return stream.WritesDone();
183 });
184
185 types::ConstrainedResponse response;
186
187 ASSERT_TRUE(stream.Read(response));
188 EXPECT_EQ(response.field(), 1);
189
190 try {
191 [[maybe_unused]] bool result = stream.Read(response);
192 ADD_FAILURE() << "Call must fail";
193 } catch (const grpc_protovalidate::client::ResponseError& err) {
194 if (streaming_settings.fail_fast) {
195 EXPECT_EQ(err.GetErrorInfo().violations_size(), 1);
196 } else {
197 EXPECT_EQ(err.GetErrorInfo().violations_size(), 20);
198 }
199 } catch (...) {
200 ADD_FAILURE() << "'InvalidArgumentError' exception expected";
201 }
202
203 write_task.Get();
204}
205
206UTEST_P(GrpcClientValidatorTest, InvalidConstraints) {
207 auto client = MakeClient<types::UnitTestServiceClient>();
208
209 try {
210 [[maybe_unused]] auto response = client.CheckInvalidResponseConstraints(google::protobuf::Empty{});
211 ADD_FAILURE() << "Call must fail";
212 } catch (const grpc_protovalidate::client::ValidatorError&) {
213 // do nothing
214 } catch (...) {
215 ADD_FAILURE() << "'ValidatorError' exception expected";
216 }
217}
218
219USERVER_NAMESPACE_END