parsed_metadata_test.cc 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. #include "src/core/lib/transport/parsed_metadata.h"
  17. #include <gmock/gmock.h>
  18. #include <gtest/gtest.h>
  19. #include "src/core/lib/slice/slice_internal.h"
  20. #include "src/core/lib/transport/metadata_batch.h"
  21. #include "test/core/util/test_config.h"
  22. namespace grpc_core {
  23. namespace testing {
  24. struct CharTrait {
  25. using MementoType = char;
  26. static absl::string_view key() { return "key"; }
  27. static char test_memento() { return 'a'; }
  28. static char test_value() { return 'a'; }
  29. static size_t test_memento_transport_size() { return 34; }
  30. static char MementoToValue(char memento) { return memento; }
  31. static char ParseMemento(Slice slice, MetadataParseErrorFn) {
  32. return slice[0];
  33. }
  34. static std::string DisplayValue(char value) { return std::string(1, value); }
  35. };
  36. struct Int32Trait {
  37. using MementoType = int32_t;
  38. static absl::string_view key() { return "key2"; }
  39. static int32_t test_memento() { return -1; }
  40. static int32_t test_value() { return -1; }
  41. static size_t test_memento_transport_size() { return 478; }
  42. static int32_t MementoToValue(int32_t memento) { return memento; }
  43. static int32_t ParseMemento(Slice slice, MetadataParseErrorFn) {
  44. int32_t out;
  45. GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out));
  46. return out;
  47. }
  48. static std::string DisplayValue(int32_t value) {
  49. return std::to_string(value);
  50. }
  51. };
  52. struct Int64Trait {
  53. using MementoType = int64_t;
  54. static absl::string_view key() { return "key3"; }
  55. static int64_t test_memento() { return 83481847284179298; }
  56. static int64_t test_value() { return -83481847284179298; }
  57. static size_t test_memento_transport_size() { return 87; }
  58. static int64_t MementoToValue(int64_t memento) { return -memento; }
  59. static int64_t ParseMemento(Slice slice, MetadataParseErrorFn) {
  60. int64_t out;
  61. GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out));
  62. return out;
  63. }
  64. static std::string DisplayValue(int64_t value) {
  65. return std::to_string(value);
  66. }
  67. };
  68. struct IntptrTrait {
  69. using MementoType = intptr_t;
  70. static absl::string_view key() { return "key4"; }
  71. static intptr_t test_memento() { return 8374298; }
  72. static intptr_t test_value() { return test_memento() / 2; }
  73. static size_t test_memento_transport_size() { return 800; }
  74. static intptr_t MementoToValue(intptr_t memento) { return memento / 2; }
  75. static intptr_t ParseMemento(Slice slice, MetadataParseErrorFn) {
  76. intptr_t out;
  77. GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out));
  78. return out;
  79. }
  80. static std::string DisplayValue(intptr_t value) {
  81. return std::to_string(value);
  82. }
  83. };
  84. struct StringTrait {
  85. using MementoType = std::string;
  86. static absl::string_view key() { return "key5-bin"; }
  87. static std::string test_memento() { return "hello"; }
  88. static std::string test_value() { return "hi hello"; }
  89. static size_t test_memento_transport_size() { return 599; }
  90. static std::string MementoToValue(std::string memento) {
  91. return "hi " + memento;
  92. }
  93. static std::string ParseMemento(Slice slice, MetadataParseErrorFn) {
  94. auto view = slice.as_string_view();
  95. return std::string(view.begin(), view.end());
  96. }
  97. static std::string DisplayValue(const std::string& value) { return value; }
  98. };
  99. class FakeContainer {
  100. public:
  101. void Set(CharTrait, char x) { SetChar(x); }
  102. void Set(Int32Trait, int32_t x) { SetInt32(x); }
  103. void Set(Int64Trait, int64_t x) { SetInt64(x); }
  104. void Set(IntptrTrait, intptr_t x) { SetIntptr(x); }
  105. void Set(StringTrait, std::string x) { SetString(x); }
  106. void Set(const ParsedMetadata<FakeContainer>& metadata) {
  107. metadata.SetOnContainer(this);
  108. }
  109. MOCK_METHOD1(SetChar, void(char));
  110. MOCK_METHOD1(SetInt32, void(int32_t));
  111. MOCK_METHOD1(SetInt64, void(int64_t));
  112. MOCK_METHOD1(SetIntptr, void(intptr_t));
  113. MOCK_METHOD1(SetString, void(std::string));
  114. };
  115. using FakeParsedMetadata = ::grpc_core::ParsedMetadata<FakeContainer>;
  116. TEST(ParsedMetadataTest, Noop) { FakeParsedMetadata(); }
  117. TEST(ParsedMetadataTest, DebugString) {
  118. FakeParsedMetadata parsed(CharTrait(), 'x', 36);
  119. EXPECT_EQ(parsed.DebugString(), "key: x");
  120. }
  121. TEST(ParsedMetadataTest, IsNotBinary) {
  122. FakeParsedMetadata parsed(CharTrait(), 'x', 36);
  123. EXPECT_FALSE(parsed.is_binary_header());
  124. }
  125. TEST(ParsedMetadataTest, IsBinary) {
  126. FakeParsedMetadata parsed(StringTrait(), "s", 36);
  127. EXPECT_TRUE(parsed.is_binary_header());
  128. }
  129. TEST(ParsedMetadataTest, Set) {
  130. FakeContainer c;
  131. FakeParsedMetadata p(CharTrait(), 'x', 36);
  132. EXPECT_CALL(c, SetChar('x')).Times(1);
  133. c.Set(p);
  134. p = FakeParsedMetadata(Int32Trait(), -1, 478);
  135. EXPECT_CALL(c, SetInt32(-1)).Times(1);
  136. c.Set(p);
  137. p = FakeParsedMetadata(Int64Trait(), 83481847284179298, 87);
  138. EXPECT_CALL(c, SetInt64(-83481847284179298)).Times(1);
  139. c.Set(p);
  140. p = FakeParsedMetadata(IntptrTrait(), 8374298, 800);
  141. EXPECT_CALL(c, SetIntptr(4187149)).Times(1);
  142. c.Set(p);
  143. p = FakeParsedMetadata(StringTrait(), "hello", 599);
  144. EXPECT_CALL(c, SetString("hi hello")).Times(1);
  145. c.Set(p);
  146. }
  147. template <typename T>
  148. class TraitSpecializedTest : public ::testing::Test {};
  149. TYPED_TEST_SUITE_P(TraitSpecializedTest);
  150. TYPED_TEST_P(TraitSpecializedTest, Noop) {
  151. FakeParsedMetadata(TypeParam(), TypeParam::test_memento(),
  152. TypeParam::test_memento_transport_size());
  153. }
  154. TYPED_TEST_P(TraitSpecializedTest, CanMove) {
  155. FakeParsedMetadata a(TypeParam(), TypeParam::test_memento(),
  156. TypeParam::test_memento_transport_size());
  157. FakeParsedMetadata b = std::move(a);
  158. a = std::move(b);
  159. }
  160. TYPED_TEST_P(TraitSpecializedTest, DebugString) {
  161. FakeParsedMetadata p(TypeParam(), TypeParam::test_memento(),
  162. TypeParam::test_memento_transport_size());
  163. EXPECT_EQ(p.DebugString(),
  164. absl::StrCat(TypeParam::key(), ": ",
  165. TypeParam::DisplayValue(TypeParam::test_memento())));
  166. }
  167. TYPED_TEST_P(TraitSpecializedTest, TransportSize) {
  168. FakeParsedMetadata p(TypeParam(), TypeParam::test_memento(),
  169. TypeParam::test_memento_transport_size());
  170. EXPECT_EQ(p.transport_size(), TypeParam::test_memento_transport_size());
  171. }
  172. REGISTER_TYPED_TEST_SUITE_P(TraitSpecializedTest, Noop, CanMove, DebugString,
  173. TransportSize);
  174. using InterestingTraits = ::testing::Types<CharTrait, Int32Trait, Int64Trait,
  175. IntptrTrait, StringTrait>;
  176. INSTANTIATE_TYPED_TEST_SUITE_P(My, TraitSpecializedTest, InterestingTraits);
  177. TEST(KeyValueTest, Simple) {
  178. using PM = ParsedMetadata<grpc_metadata_batch>;
  179. using PMPtr = std::unique_ptr<PM>;
  180. PMPtr p = absl::make_unique<PM>(Slice::FromCopiedString("key"),
  181. Slice::FromCopiedString("value"));
  182. EXPECT_EQ(p->DebugString(), "key: value");
  183. EXPECT_EQ(p->transport_size(), 40);
  184. PM p2 = p->WithNewValue(Slice::FromCopiedString("some_other_value"),
  185. [](absl::string_view msg, const Slice& value) {
  186. ASSERT_TRUE(false)
  187. << "Should not be called: msg=" << msg
  188. << ", value=" << value.as_string_view();
  189. });
  190. EXPECT_EQ(p->DebugString(), "key: value");
  191. EXPECT_EQ(p2.DebugString(), "key: some_other_value");
  192. EXPECT_EQ(p2.transport_size(), 51);
  193. p.reset();
  194. EXPECT_EQ(p2.DebugString(), "key: some_other_value");
  195. EXPECT_EQ(p2.transport_size(), 51);
  196. PM p3 = std::move(p2);
  197. EXPECT_EQ(p3.DebugString(), "key: some_other_value");
  198. EXPECT_EQ(p3.transport_size(), 51);
  199. }
  200. TEST(KeyValueTest, LongKey) {
  201. using PM = ParsedMetadata<grpc_metadata_batch>;
  202. using PMPtr = std::unique_ptr<PM>;
  203. PMPtr p = absl::make_unique<PM>(Slice::FromCopiedString(std::string(60, 'a')),
  204. Slice::FromCopiedString("value"));
  205. EXPECT_EQ(
  206. p->DebugString(),
  207. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: value");
  208. EXPECT_EQ(p->transport_size(), 97);
  209. PM p2 = p->WithNewValue(Slice::FromCopiedString("some_other_value"),
  210. [](absl::string_view msg, const Slice& value) {
  211. ASSERT_TRUE(false)
  212. << "Should not be called: msg=" << msg
  213. << ", value=" << value.as_string_view();
  214. });
  215. EXPECT_EQ(
  216. p->DebugString(),
  217. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: value");
  218. EXPECT_EQ(p2.DebugString(),
  219. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: "
  220. "some_other_value");
  221. EXPECT_EQ(p2.transport_size(), 108);
  222. p.reset();
  223. EXPECT_EQ(p2.DebugString(),
  224. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: "
  225. "some_other_value");
  226. EXPECT_EQ(p2.transport_size(), 108);
  227. PM p3 = std::move(p2);
  228. EXPECT_EQ(p3.DebugString(),
  229. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: "
  230. "some_other_value");
  231. EXPECT_EQ(p3.transport_size(), 108);
  232. }
  233. } // namespace testing
  234. } // namespace grpc_core
  235. int main(int argc, char** argv) {
  236. testing::InitGoogleTest(&argc, argv);
  237. grpc::testing::TestEnvironment env(argc, argv);
  238. return RUN_ALL_TESTS();
  239. };