4#include <gmock/gmock.h>
5#include <grpcpp/support/status.h>
6#include <gtest/gtest.h>
8#include <userver/engine/task/task.hpp>
9#include <userver/engine/wait_all_checked.hpp>
10#include <userver/utest/assert_macros.hpp>
11#include <userver/utest/utest.hpp>
12#include <userver/utils/async.hpp>
14#include <userver/grpc-protovalidate/validate.hpp>
17USERVER_NAMESPACE_BEGIN
19UTEST(ValidateTest, Valid) {
20 auto result = grpc_protovalidate::ValidateMessage(tests::CreateValidMessage(2));
21 EXPECT_TRUE(result.IsSuccess());
22 UEXPECT_THROW_MSG(result.GetError(), std::logic_error,
"Requested error for success validation result");
25UTEST_MT(ValidateTest, ValidMultithreaded, 4) {
26 std::vector<engine::Task> tasks;
27 for (std::size_t i = 1; i < 250; ++i) {
28 tasks.emplace_back(utils::Async(
"ValidateTestMultithreaded", [i]() {
29 auto _ = grpc_protovalidate::ValidateMessage(tests::CreateValidMessage(i));
32 UEXPECT_NO_THROW(engine::WaitAllChecked(tasks));
35UTEST(EnsureValidTest, InvalidDefault) {
36 constexpr auto kExpectedMessage =
"Message 'types.ConstrainedMessage' validation error: 18 constraint(s) violated";
37 auto result = grpc_protovalidate::ValidateMessage(tests::CreateInvalidMessage());
39 ASSERT_FALSE(result.IsSuccess());
40 const auto error = std::move(result).GetError();
42 EXPECT_EQ(error.GetType(), grpc_protovalidate::ValidationError::Type::kRule);
43 EXPECT_EQ(error.GetMessageName(),
"types.ConstrainedMessage");
44 EXPECT_EQ(error.GetDescription(), kExpectedMessage);
45 EXPECT_THAT(error.GetViolations(), testing::SizeIs(18));
47 const grpc::Status status_no_details = error.GetGrpcStatus(
false);
48 EXPECT_EQ(status_no_details.error_code(), grpc::StatusCode::INVALID_ARGUMENT);
49 EXPECT_EQ(status_no_details.error_message(), kExpectedMessage);
51 const grpc::Status status_with_details = error.GetGrpcStatus(
true);
52 EXPECT_EQ(status_with_details.error_code(), grpc::StatusCode::INVALID_ARGUMENT);
53 EXPECT_EQ(status_with_details.error_message(), kExpectedMessage);
54 EXPECT_GT(status_with_details.error_details().size(), 0);
57UTEST(EnsureValidTest, InvalidFailFast) {
58 constexpr auto kExpectedMessage =
"Message 'types.ConstrainedMessage' validation error: 1 constraint(s) violated";
59 const auto result = grpc_protovalidate::ValidateMessage(tests::CreateInvalidMessage(), {.fail_fast =
true});
61 ASSERT_FALSE(result.IsSuccess());
62 const auto error = std::move(result).GetError();
64 EXPECT_EQ(error.GetType(), grpc_protovalidate::ValidationError::Type::kRule);
65 EXPECT_EQ(error.GetMessageName(),
"types.ConstrainedMessage");
66 EXPECT_EQ(error.GetDescription(), kExpectedMessage);
67 EXPECT_THAT(error.GetViolations(), testing::SizeIs(1));
69 const grpc::Status status_no_details = error.GetGrpcStatus(
false);
70 EXPECT_EQ(status_no_details.error_code(), grpc::StatusCode::INVALID_ARGUMENT);
71 EXPECT_EQ(status_no_details.error_message(), kExpectedMessage);
73 const grpc::Status status_with_details = error.GetGrpcStatus(
true);
74 EXPECT_EQ(status_with_details.error_code(), grpc::StatusCode::INVALID_ARGUMENT);
75 EXPECT_EQ(status_with_details.error_message(), kExpectedMessage);
76 EXPECT_GT(status_with_details.error_details().size(), 0);
79UTEST(EnsureValidTest, InvalidConstraintsDefault) {
80 constexpr auto kExpectedMessage =
81 "Message 'types.InvalidConstraints' validation error: internal protovalidate error (check constraints "
82 "syntax in the proto file) - INVALID_ARGUMENT: no_such_field : non_existent_field";
83 const auto result = grpc_protovalidate::ValidateMessage(types::InvalidConstraints(), {.fail_fast =
true});
85 ASSERT_FALSE(result.IsSuccess());
86 const auto error = std::move(result).GetError();
88 EXPECT_EQ(error.GetType(), grpc_protovalidate::ValidationError::Type::kInternal);
89 EXPECT_EQ(error.GetMessageName(),
"types.InvalidConstraints");
90 EXPECT_EQ(error.GetDescription(), kExpectedMessage);
91 EXPECT_THAT(error.GetViolations(), testing::SizeIs(0));
93 const grpc::Status status = error.GetGrpcStatus();
94 EXPECT_EQ(status.error_code(), grpc::StatusCode::INTERNAL);
95 EXPECT_EQ(status.error_message(), kExpectedMessage);