1 // Copyright 2023 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "gmock/gmock.h"
16
17 #include "test/core/transport/test_suite/test.h"
18
19 using testing::UnorderedElementsAreArray;
20
21 namespace grpc_core {
22
23 namespace {
24 class LoweringEncoder {
25 public:
Take()26 std::vector<std::pair<std::string, std::string>> Take() {
27 return std::move(metadata_);
28 }
29
Encode(const Slice & key,const Slice & value)30 void Encode(const Slice& key, const Slice& value) {
31 metadata_.emplace_back(key.as_string_view(), value.as_string_view());
32 }
33
34 template <typename Which>
Encode(Which,const typename Which::ValueType & value)35 void Encode(Which, const typename Which::ValueType& value) {
36 metadata_.emplace_back(Which::key(), Which::Encode(value).as_string_view());
37 }
38
39 private:
40 std::vector<std::pair<std::string, std::string>> metadata_;
41 };
42
LowerMetadata(const grpc_metadata_batch & metadata)43 std::vector<std::pair<std::string, std::string>> LowerMetadata(
44 const grpc_metadata_batch& metadata) {
45 LoweringEncoder encoder;
46 metadata.Encode(&encoder);
47 return encoder.Take();
48 }
49
FillMetadata(const std::vector<std::pair<std::string,std::string>> & md,grpc_metadata_batch & out)50 void FillMetadata(const std::vector<std::pair<std::string, std::string>>& md,
51 grpc_metadata_batch& out) {
52 for (const auto& p : md) {
53 out.Append(p.first, Slice::FromCopiedString(p.second),
54 [&](absl::string_view error, const Slice& value) {
55 Crash(absl::StrCat(
56 "Failed to parse metadata for '", p.first, "': ", error,
57 " value=", absl::CEscape(value.as_string_view())));
58 });
59 }
60 }
61
62 } // namespace
63
TRANSPORT_TEST(UnaryWithSomeContent)64 TRANSPORT_TEST(UnaryWithSomeContent) {
65 SetServerAcceptor();
66 auto initiator = CreateCall();
67 const auto client_initial_metadata = RandomMetadata();
68 const auto server_initial_metadata = RandomMetadata();
69 const auto server_trailing_metadata = RandomMetadata();
70 const auto client_payload = RandomMessage();
71 const auto server_payload = RandomMessage();
72 SpawnTestSeq(
73 initiator, "initiator",
74 [&]() {
75 auto md = Arena::MakePooled<ClientMetadata>();
76 FillMetadata(client_initial_metadata, *md);
77 return initiator.PushClientInitialMetadata(std::move(md));
78 },
79 [&](StatusFlag status) mutable {
80 EXPECT_TRUE(status.ok());
81 return initiator.PushMessage(Arena::MakePooled<Message>(
82 SliceBuffer(Slice::FromCopiedString(client_payload)), 0));
83 },
84 [&](StatusFlag status) mutable {
85 EXPECT_TRUE(status.ok());
86 initiator.FinishSends();
87 return initiator.PullServerInitialMetadata();
88 },
89 [&](ValueOrFailure<absl::optional<ServerMetadataHandle>> md) {
90 EXPECT_TRUE(md.ok());
91 EXPECT_TRUE(md.value().has_value());
92 EXPECT_THAT(LowerMetadata(***md),
93 UnorderedElementsAreArray(server_initial_metadata));
94 return initiator.PullMessage();
95 },
96 [&](NextResult<MessageHandle> msg) {
97 EXPECT_TRUE(msg.has_value());
98 EXPECT_EQ(msg.value()->payload()->JoinIntoString(), server_payload);
99 return initiator.PullMessage();
100 },
101 [&](NextResult<MessageHandle> msg) {
102 EXPECT_FALSE(msg.has_value());
103 EXPECT_FALSE(msg.cancelled());
104 return initiator.PullServerTrailingMetadata();
105 },
106 [&](ValueOrFailure<ServerMetadataHandle> md) {
107 EXPECT_TRUE(md.ok());
108 EXPECT_THAT(LowerMetadata(**md),
109 UnorderedElementsAreArray(server_trailing_metadata));
110 return Empty{};
111 });
112 auto handler = TickUntilServerCall();
113 SpawnTestSeq(
114 handler, "handler", [&] { return handler.PullClientInitialMetadata(); },
115 [&](ValueOrFailure<ServerMetadataHandle> md) {
116 EXPECT_TRUE(md.ok());
117 EXPECT_THAT(LowerMetadata(**md),
118 UnorderedElementsAreArray(client_initial_metadata));
119 return handler.PullMessage();
120 },
121 [&](NextResult<MessageHandle> msg) {
122 EXPECT_TRUE(msg.has_value());
123 EXPECT_EQ(msg.value()->payload()->JoinIntoString(), client_payload);
124 return handler.PullMessage();
125 },
126 [&](NextResult<MessageHandle> msg) {
127 EXPECT_FALSE(msg.has_value());
128 EXPECT_FALSE(msg.cancelled());
129 auto md = Arena::MakePooled<ServerMetadata>();
130 FillMetadata(server_initial_metadata, *md);
131 return handler.PushServerInitialMetadata(std::move(md));
132 },
133 [&](StatusFlag result) mutable {
134 EXPECT_TRUE(result.ok());
135 return handler.PushMessage(Arena::MakePooled<Message>(
136 SliceBuffer(Slice::FromCopiedString(server_payload)), 0));
137 },
138 [&](StatusFlag result) mutable {
139 EXPECT_TRUE(result.ok());
140 auto md = Arena::MakePooled<ServerMetadata>();
141 FillMetadata(server_trailing_metadata, *md);
142 return handler.PushServerTrailingMetadata(std::move(md));
143 },
144 [&](StatusFlag result) mutable {
145 EXPECT_TRUE(result.ok());
146 return Empty{};
147 });
148 WaitForAllPendingWork();
149 }
150
151 } // namespace grpc_core
152