xref: /aosp_15_r20/external/grpc-grpc/test/core/transport/parsed_metadata_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 // Copyright 2021 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "src/core/lib/transport/parsed_metadata.h"
18 
19 #include <memory>
20 
21 #include "absl/strings/numbers.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 
25 #include <grpc/support/log.h>
26 
27 #include "src/core/lib/transport/metadata_batch.h"
28 #include "test/core/util/test_config.h"
29 
30 namespace grpc_core {
31 namespace testing {
32 
33 struct CharTrait {
34   using MementoType = char;
keygrpc_core::testing::CharTrait35   static absl::string_view key() { return "key"; }
test_mementogrpc_core::testing::CharTrait36   static char test_memento() { return 'a'; }
test_valuegrpc_core::testing::CharTrait37   static char test_value() { return 'a'; }
test_memento_transport_sizegrpc_core::testing::CharTrait38   static size_t test_memento_transport_size() { return 34; }
MementoToValuegrpc_core::testing::CharTrait39   static char MementoToValue(char memento) { return memento; }
ParseMementogrpc_core::testing::CharTrait40   static char ParseMemento(Slice slice, bool, MetadataParseErrorFn) {
41     return slice[0];
42   }
DisplayValuegrpc_core::testing::CharTrait43   static std::string DisplayValue(char value) { return std::string(1, value); }
DisplayMementogrpc_core::testing::CharTrait44   static std::string DisplayMemento(MementoType memento) {
45     return DisplayValue(memento);
46   }
47 };
48 
49 struct Int32Trait {
50   using MementoType = int32_t;
keygrpc_core::testing::Int32Trait51   static absl::string_view key() { return "key2"; }
test_mementogrpc_core::testing::Int32Trait52   static int32_t test_memento() { return -1; }
test_valuegrpc_core::testing::Int32Trait53   static int32_t test_value() { return -1; }
test_memento_transport_sizegrpc_core::testing::Int32Trait54   static size_t test_memento_transport_size() { return 478; }
MementoToValuegrpc_core::testing::Int32Trait55   static int32_t MementoToValue(int32_t memento) { return memento; }
ParseMementogrpc_core::testing::Int32Trait56   static int32_t ParseMemento(Slice slice, bool, MetadataParseErrorFn) {
57     int32_t out;
58     GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out));
59     return out;
60   }
DisplayValuegrpc_core::testing::Int32Trait61   static std::string DisplayValue(int32_t value) {
62     return std::to_string(value);
63   }
DisplayMementogrpc_core::testing::Int32Trait64   static std::string DisplayMemento(MementoType memento) {
65     return DisplayValue(memento);
66   }
67 };
68 
69 struct Int64Trait {
70   using MementoType = int64_t;
keygrpc_core::testing::Int64Trait71   static absl::string_view key() { return "key3"; }
test_mementogrpc_core::testing::Int64Trait72   static int64_t test_memento() { return 83481847284179298; }
test_valuegrpc_core::testing::Int64Trait73   static int64_t test_value() { return -83481847284179298; }
test_memento_transport_sizegrpc_core::testing::Int64Trait74   static size_t test_memento_transport_size() { return 87; }
MementoToValuegrpc_core::testing::Int64Trait75   static int64_t MementoToValue(int64_t memento) { return -memento; }
ParseMementogrpc_core::testing::Int64Trait76   static int64_t ParseMemento(Slice slice, bool, MetadataParseErrorFn) {
77     int64_t out;
78     GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out));
79     return out;
80   }
DisplayValuegrpc_core::testing::Int64Trait81   static std::string DisplayValue(int64_t value) {
82     return std::to_string(value);
83   }
DisplayMementogrpc_core::testing::Int64Trait84   static std::string DisplayMemento(MementoType memento) {
85     return DisplayValue(memento);
86   }
87 };
88 
89 struct IntptrTrait {
90   using MementoType = intptr_t;
keygrpc_core::testing::IntptrTrait91   static absl::string_view key() { return "key4"; }
test_mementogrpc_core::testing::IntptrTrait92   static intptr_t test_memento() { return 8374298; }
test_valuegrpc_core::testing::IntptrTrait93   static intptr_t test_value() { return test_memento() / 2; }
test_memento_transport_sizegrpc_core::testing::IntptrTrait94   static size_t test_memento_transport_size() { return 800; }
MementoToValuegrpc_core::testing::IntptrTrait95   static intptr_t MementoToValue(intptr_t memento) { return memento / 2; }
ParseMementogrpc_core::testing::IntptrTrait96   static intptr_t ParseMemento(Slice slice, bool, MetadataParseErrorFn) {
97     intptr_t out;
98     GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out));
99     return out;
100   }
DisplayValuegrpc_core::testing::IntptrTrait101   static std::string DisplayValue(intptr_t value) {
102     return std::to_string(value);
103   }
DisplayMementogrpc_core::testing::IntptrTrait104   static std::string DisplayMemento(MementoType memento) {
105     return DisplayValue(memento);
106   }
107 };
108 
109 struct StringTrait {
110   using MementoType = std::string;
keygrpc_core::testing::StringTrait111   static absl::string_view key() { return "key5-bin"; }
test_mementogrpc_core::testing::StringTrait112   static std::string test_memento() { return "hello"; }
test_valuegrpc_core::testing::StringTrait113   static std::string test_value() { return "hi hello"; }
test_memento_transport_sizegrpc_core::testing::StringTrait114   static size_t test_memento_transport_size() { return 599; }
MementoToValuegrpc_core::testing::StringTrait115   static std::string MementoToValue(std::string memento) {
116     return "hi " + memento;
117   }
ParseMementogrpc_core::testing::StringTrait118   static std::string ParseMemento(Slice slice, bool, MetadataParseErrorFn) {
119     auto view = slice.as_string_view();
120     return std::string(view.begin(), view.end());
121   }
DisplayValuegrpc_core::testing::StringTrait122   static std::string DisplayValue(const std::string& value) { return value; }
DisplayMementogrpc_core::testing::StringTrait123   static std::string DisplayMemento(MementoType memento) {
124     return DisplayValue(memento);
125   }
126 };
127 
128 class FakeContainer {
129  public:
Set(CharTrait,char x)130   void Set(CharTrait, char x) { SetChar(x); }
Set(Int32Trait,int32_t x)131   void Set(Int32Trait, int32_t x) { SetInt32(x); }
Set(Int64Trait,int64_t x)132   void Set(Int64Trait, int64_t x) { SetInt64(x); }
Set(IntptrTrait,intptr_t x)133   void Set(IntptrTrait, intptr_t x) { SetIntptr(x); }
Set(StringTrait,std::string x)134   void Set(StringTrait, std::string x) { SetString(x); }
135 
Set(const ParsedMetadata<FakeContainer> & metadata)136   void Set(const ParsedMetadata<FakeContainer>& metadata) {
137     metadata.SetOnContainer(this);
138   }
139 
140   MOCK_METHOD1(SetChar, void(char));
141   MOCK_METHOD1(SetInt32, void(int32_t));
142   MOCK_METHOD1(SetInt64, void(int64_t));
143   MOCK_METHOD1(SetIntptr, void(intptr_t));
144   MOCK_METHOD1(SetString, void(std::string));
145 };
146 
147 using FakeParsedMetadata = ::grpc_core::ParsedMetadata<FakeContainer>;
148 
TEST(ParsedMetadataTest,Noop)149 TEST(ParsedMetadataTest, Noop) { FakeParsedMetadata(); }
150 
TEST(ParsedMetadataTest,DebugString)151 TEST(ParsedMetadataTest, DebugString) {
152   FakeParsedMetadata parsed(CharTrait(), 'x', 36);
153   EXPECT_EQ(parsed.DebugString(), "key: x");
154 }
155 
TEST(ParsedMetadataTest,IsNotBinary)156 TEST(ParsedMetadataTest, IsNotBinary) {
157   FakeParsedMetadata parsed(CharTrait(), 'x', 36);
158   EXPECT_FALSE(parsed.is_binary_header());
159 }
160 
TEST(ParsedMetadataTest,IsBinary)161 TEST(ParsedMetadataTest, IsBinary) {
162   FakeParsedMetadata parsed(StringTrait(), "s", 36);
163   EXPECT_TRUE(parsed.is_binary_header());
164 }
165 
TEST(ParsedMetadataTest,Set)166 TEST(ParsedMetadataTest, Set) {
167   FakeContainer c;
168   FakeParsedMetadata p(CharTrait(), 'x', 36);
169   EXPECT_CALL(c, SetChar('x')).Times(1);
170   c.Set(p);
171   p = FakeParsedMetadata(Int32Trait(), -1, 478);
172   EXPECT_CALL(c, SetInt32(-1)).Times(1);
173   c.Set(p);
174   p = FakeParsedMetadata(Int64Trait(), 83481847284179298, 87);
175   EXPECT_CALL(c, SetInt64(-83481847284179298)).Times(1);
176   c.Set(p);
177   p = FakeParsedMetadata(IntptrTrait(), 8374298, 800);
178   EXPECT_CALL(c, SetIntptr(4187149)).Times(1);
179   c.Set(p);
180   p = FakeParsedMetadata(StringTrait(), "hello", 599);
181   EXPECT_CALL(c, SetString("hi hello")).Times(1);
182   c.Set(p);
183 }
184 
185 template <typename T>
186 class TraitSpecializedTest : public ::testing::Test {};
187 
188 TYPED_TEST_SUITE_P(TraitSpecializedTest);
189 
TYPED_TEST_P(TraitSpecializedTest,Noop)190 TYPED_TEST_P(TraitSpecializedTest, Noop) {
191   FakeParsedMetadata(TypeParam(), TypeParam::test_memento(),
192                      TypeParam::test_memento_transport_size());
193 }
194 
TYPED_TEST_P(TraitSpecializedTest,CanMove)195 TYPED_TEST_P(TraitSpecializedTest, CanMove) {
196   FakeParsedMetadata a(TypeParam(), TypeParam::test_memento(),
197                        TypeParam::test_memento_transport_size());
198   FakeParsedMetadata b = std::move(a);
199   a = std::move(b);
200 }
201 
TYPED_TEST_P(TraitSpecializedTest,DebugString)202 TYPED_TEST_P(TraitSpecializedTest, DebugString) {
203   FakeParsedMetadata p(TypeParam(), TypeParam::test_memento(),
204                        TypeParam::test_memento_transport_size());
205   EXPECT_EQ(p.DebugString(),
206             absl::StrCat(TypeParam::key(), ": ",
207                          TypeParam::DisplayValue(TypeParam::test_memento())));
208 }
209 
TYPED_TEST_P(TraitSpecializedTest,TransportSize)210 TYPED_TEST_P(TraitSpecializedTest, TransportSize) {
211   FakeParsedMetadata p(TypeParam(), TypeParam::test_memento(),
212                        TypeParam::test_memento_transport_size());
213   EXPECT_EQ(p.transport_size(), TypeParam::test_memento_transport_size());
214 }
215 
216 REGISTER_TYPED_TEST_SUITE_P(TraitSpecializedTest, Noop, CanMove, DebugString,
217                             TransportSize);
218 
219 using InterestingTraits = ::testing::Types<CharTrait, Int32Trait, Int64Trait,
220                                            IntptrTrait, StringTrait>;
221 INSTANTIATE_TYPED_TEST_SUITE_P(My, TraitSpecializedTest, InterestingTraits);
222 
TEST(KeyValueTest,Simple)223 TEST(KeyValueTest, Simple) {
224   using PM = ParsedMetadata<grpc_metadata_batch>;
225   using PMPtr = std::unique_ptr<PM>;
226   PMPtr p =
227       std::make_unique<PM>(PM::FromSlicePair{}, Slice::FromCopiedString("key"),
228                            Slice::FromCopiedString("value"), 40);
229   EXPECT_EQ(p->DebugString(), "key: value");
230   EXPECT_EQ(p->transport_size(), 40);
231   PM p2 = p->WithNewValue(Slice::FromCopiedString("some_other_value"), true,
232                           strlen("some_other_value"),
233                           [](absl::string_view msg, const Slice& value) {
234                             ASSERT_TRUE(false)
235                                 << "Should not be called: msg=" << msg
236                                 << ", value=" << value.as_string_view();
237                           });
238   EXPECT_EQ(p->DebugString(), "key: value");
239   EXPECT_EQ(p2.DebugString(), "key: some_other_value");
240   EXPECT_EQ(p2.transport_size(), 51);
241   p.reset();
242   EXPECT_EQ(p2.DebugString(), "key: some_other_value");
243   EXPECT_EQ(p2.transport_size(), 51);
244   PM p3 = std::move(p2);
245   EXPECT_EQ(p3.DebugString(), "key: some_other_value");
246   EXPECT_EQ(p3.transport_size(), 51);
247 }
248 
TEST(KeyValueTest,LongKey)249 TEST(KeyValueTest, LongKey) {
250   using PM = ParsedMetadata<grpc_metadata_batch>;
251   using PMPtr = std::unique_ptr<PM>;
252   PMPtr p = std::make_unique<PM>(PM::FromSlicePair{},
253                                  Slice::FromCopiedString(std::string(60, 'a')),
254                                  Slice::FromCopiedString("value"), 60 + 5 + 32);
255   EXPECT_EQ(
256       p->DebugString(),
257       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: value");
258   EXPECT_EQ(p->transport_size(), 97);
259   PM p2 = p->WithNewValue(Slice::FromCopiedString("some_other_value"), true,
260                           strlen("some_other_value"),
261                           [](absl::string_view msg, const Slice& value) {
262                             ASSERT_TRUE(false)
263                                 << "Should not be called: msg=" << msg
264                                 << ", value=" << value.as_string_view();
265                           });
266   EXPECT_EQ(
267       p->DebugString(),
268       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: value");
269   EXPECT_EQ(p2.DebugString(),
270             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: "
271             "some_other_value");
272   EXPECT_EQ(p2.transport_size(), 108);
273   p.reset();
274   EXPECT_EQ(p2.DebugString(),
275             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: "
276             "some_other_value");
277   EXPECT_EQ(p2.transport_size(), 108);
278   PM p3 = std::move(p2);
279   EXPECT_EQ(p3.DebugString(),
280             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: "
281             "some_other_value");
282   EXPECT_EQ(p3.transport_size(), 108);
283 }
284 
285 }  // namespace testing
286 }  // namespace grpc_core
287 
main(int argc,char ** argv)288 int main(int argc, char** argv) {
289   testing::InitGoogleTest(&argc, argv);
290   grpc::testing::TestEnvironment env(&argc, argv);
291   return RUN_ALL_TESTS();
292 };
293