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 <gmock/gmock.h>
20 #include <gtest/gtest.h>
21
22 #include "src/core/lib/slice/slice_internal.h"
23 #include "test/core/util/test_config.h"
24
25 namespace grpc_core {
26 namespace testing {
27
28 struct CharTrait {
29 using MementoType = char;
keygrpc_core::testing::CharTrait30 static const char* key() { return "key"; }
test_mementogrpc_core::testing::CharTrait31 static char test_memento() { return 'a'; }
test_valuegrpc_core::testing::CharTrait32 static char test_value() { return 'a'; }
test_memento_transport_sizegrpc_core::testing::CharTrait33 static size_t test_memento_transport_size() { return 34; }
MementoToValuegrpc_core::testing::CharTrait34 static char MementoToValue(char memento) { return memento; }
ParseMementogrpc_core::testing::CharTrait35 static char ParseMemento(const grpc_slice& slice) {
36 return *GRPC_SLICE_START_PTR(slice);
37 }
DisplayValuegrpc_core::testing::CharTrait38 static std::string DisplayValue(char value) { return std::string(1, value); }
39 };
40
41 struct Int32Trait {
42 using MementoType = int32_t;
keygrpc_core::testing::Int32Trait43 static const char* key() { return "key2"; }
test_mementogrpc_core::testing::Int32Trait44 static int32_t test_memento() { return -1; }
test_valuegrpc_core::testing::Int32Trait45 static int32_t test_value() { return -1; }
test_memento_transport_sizegrpc_core::testing::Int32Trait46 static size_t test_memento_transport_size() { return 478; }
MementoToValuegrpc_core::testing::Int32Trait47 static int32_t MementoToValue(int32_t memento) { return memento; }
ParseMementogrpc_core::testing::Int32Trait48 static int32_t ParseMemento(const grpc_slice& slice) {
49 int32_t out;
50 GPR_ASSERT(absl::SimpleAtoi(StringViewFromSlice(slice), &out));
51 return out;
52 }
DisplayValuegrpc_core::testing::Int32Trait53 static std::string DisplayValue(int32_t value) {
54 return std::to_string(value);
55 }
56 };
57
58 struct Int64Trait {
59 using MementoType = int64_t;
keygrpc_core::testing::Int64Trait60 static const char* key() { return "key3"; }
test_mementogrpc_core::testing::Int64Trait61 static int64_t test_memento() { return 83481847284179298; }
test_valuegrpc_core::testing::Int64Trait62 static int64_t test_value() { return -83481847284179298; }
test_memento_transport_sizegrpc_core::testing::Int64Trait63 static size_t test_memento_transport_size() { return 87; }
MementoToValuegrpc_core::testing::Int64Trait64 static int64_t MementoToValue(int64_t memento) { return -memento; }
ParseMementogrpc_core::testing::Int64Trait65 static int64_t ParseMemento(const grpc_slice& slice) {
66 int64_t out;
67 GPR_ASSERT(absl::SimpleAtoi(StringViewFromSlice(slice), &out));
68 return out;
69 }
DisplayValuegrpc_core::testing::Int64Trait70 static std::string DisplayValue(int64_t value) {
71 return std::to_string(value);
72 }
73 };
74
75 struct IntptrTrait {
76 using MementoType = intptr_t;
keygrpc_core::testing::IntptrTrait77 static const char* key() { return "key4"; }
test_mementogrpc_core::testing::IntptrTrait78 static intptr_t test_memento() { return 8374298; }
test_valuegrpc_core::testing::IntptrTrait79 static intptr_t test_value() { return test_memento() / 2; }
test_memento_transport_sizegrpc_core::testing::IntptrTrait80 static size_t test_memento_transport_size() { return 800; }
MementoToValuegrpc_core::testing::IntptrTrait81 static intptr_t MementoToValue(intptr_t memento) { return memento / 2; }
ParseMementogrpc_core::testing::IntptrTrait82 static intptr_t ParseMemento(const grpc_slice& slice) {
83 intptr_t out;
84 GPR_ASSERT(absl::SimpleAtoi(StringViewFromSlice(slice), &out));
85 return out;
86 }
DisplayValuegrpc_core::testing::IntptrTrait87 static std::string DisplayValue(intptr_t value) {
88 return std::to_string(value);
89 }
90 };
91
92 struct StringTrait {
93 using MementoType = std::string;
keygrpc_core::testing::StringTrait94 static const char* key() { return "key5-bin"; }
test_mementogrpc_core::testing::StringTrait95 static std::string test_memento() { return "hello"; }
test_valuegrpc_core::testing::StringTrait96 static std::string test_value() { return "hi hello"; }
test_memento_transport_sizegrpc_core::testing::StringTrait97 static size_t test_memento_transport_size() { return 599; }
MementoToValuegrpc_core::testing::StringTrait98 static std::string MementoToValue(std::string memento) {
99 return "hi " + memento;
100 }
ParseMementogrpc_core::testing::StringTrait101 static std::string ParseMemento(const grpc_slice& slice) {
102 auto view = StringViewFromSlice(slice);
103 return std::string(view.begin(), view.end());
104 }
DisplayValuegrpc_core::testing::StringTrait105 static std::string DisplayValue(const std::string& value) { return value; }
106 };
107
108 class FakeContainer {
109 public:
Set(CharTrait,char x)110 void Set(CharTrait, char x) { SetChar(x); }
Set(Int32Trait,int32_t x)111 void Set(Int32Trait, int32_t x) { SetInt32(x); }
Set(Int64Trait,int64_t x)112 void Set(Int64Trait, int64_t x) { SetInt64(x); }
Set(IntptrTrait,intptr_t x)113 void Set(IntptrTrait, intptr_t x) { SetIntptr(x); }
Set(StringTrait,std::string x)114 void Set(StringTrait, std::string x) { SetString(x); }
115
Set(const::grpc_core::ParsedMetadata<FakeContainer> & metadata)116 void Set(const ::grpc_core::ParsedMetadata<FakeContainer>& metadata) {
117 EXPECT_EQ(GRPC_ERROR_NONE, metadata.SetOnContainer(this));
118 }
119
120 MOCK_METHOD1(SetChar, void(char));
121 MOCK_METHOD1(SetInt32, void(int32_t));
122 MOCK_METHOD1(SetInt64, void(int64_t));
123 MOCK_METHOD1(SetIntptr, void(intptr_t));
124 MOCK_METHOD1(SetString, void(std::string));
125 };
126
127 using ParsedMetadata = ::grpc_core::ParsedMetadata<FakeContainer>;
128
TEST(ParsedMetadataTest,Noop)129 TEST(ParsedMetadataTest, Noop) { ParsedMetadata(); }
130
TEST(ParsedMetadataTest,DebugString)131 TEST(ParsedMetadataTest, DebugString) {
132 ParsedMetadata parsed(CharTrait(), 'x', 36);
133 EXPECT_EQ(parsed.DebugString(), "key: x");
134 }
135
TEST(ParsedMetadataTest,IsNotBinary)136 TEST(ParsedMetadataTest, IsNotBinary) {
137 ParsedMetadata parsed(CharTrait(), 'x', 36);
138 EXPECT_FALSE(parsed.is_binary_header());
139 }
140
TEST(ParsedMetadataTest,IsBinary)141 TEST(ParsedMetadataTest, IsBinary) {
142 ParsedMetadata parsed(StringTrait(), "s", 36);
143 EXPECT_TRUE(parsed.is_binary_header());
144 }
145
TEST(ParsedMetadataTest,Set)146 TEST(ParsedMetadataTest, Set) {
147 FakeContainer c;
148 ParsedMetadata p(CharTrait(), 'x', 36);
149 EXPECT_CALL(c, SetChar('x')).Times(1);
150 c.Set(p);
151 p = ParsedMetadata(Int32Trait(), -1, 478);
152 EXPECT_CALL(c, SetInt32(-1)).Times(1);
153 c.Set(p);
154 p = ParsedMetadata(Int64Trait(), 83481847284179298, 87);
155 EXPECT_CALL(c, SetInt64(-83481847284179298)).Times(1);
156 c.Set(p);
157 p = ParsedMetadata(IntptrTrait(), 8374298, 800);
158 EXPECT_CALL(c, SetIntptr(4187149)).Times(1);
159 c.Set(p);
160 p = ParsedMetadata(StringTrait(), "hello", 599);
161 EXPECT_CALL(c, SetString("hi hello")).Times(1);
162 c.Set(p);
163 }
164
165 template <typename T>
166 class TraitSpecializedTest : public ::testing::Test {};
167
168 TYPED_TEST_SUITE_P(TraitSpecializedTest);
169
TYPED_TEST_P(TraitSpecializedTest,Noop)170 TYPED_TEST_P(TraitSpecializedTest, Noop) {
171 ParsedMetadata(TypeParam(), TypeParam::test_memento(),
172 TypeParam::test_memento_transport_size());
173 }
174
TYPED_TEST_P(TraitSpecializedTest,CanMove)175 TYPED_TEST_P(TraitSpecializedTest, CanMove) {
176 ParsedMetadata a(TypeParam(), TypeParam::test_memento(),
177 TypeParam::test_memento_transport_size());
178 ParsedMetadata b = std::move(a);
179 a = std::move(b);
180 }
181
TYPED_TEST_P(TraitSpecializedTest,DebugString)182 TYPED_TEST_P(TraitSpecializedTest, DebugString) {
183 ParsedMetadata p(TypeParam(), TypeParam::test_memento(),
184 TypeParam::test_memento_transport_size());
185 EXPECT_EQ(p.DebugString(),
186 absl::StrCat(TypeParam::key(), ": ",
187 TypeParam::DisplayValue(TypeParam::test_memento())));
188 }
189
TYPED_TEST_P(TraitSpecializedTest,TransportSize)190 TYPED_TEST_P(TraitSpecializedTest, TransportSize) {
191 ParsedMetadata p(TypeParam(), TypeParam::test_memento(),
192 TypeParam::test_memento_transport_size());
193 EXPECT_EQ(p.transport_size(), TypeParam::test_memento_transport_size());
194 }
195
196 REGISTER_TYPED_TEST_SUITE_P(TraitSpecializedTest, Noop, CanMove, DebugString,
197 TransportSize);
198
199 using InterestingTraits = ::testing::Types<CharTrait, Int32Trait, Int64Trait,
200 IntptrTrait, StringTrait>;
201 INSTANTIATE_TYPED_TEST_SUITE_P(My, TraitSpecializedTest, InterestingTraits);
202
203 } // namespace testing
204 } // namespace grpc_core
205
main(int argc,char ** argv)206 int main(int argc, char** argv) {
207 testing::InitGoogleTest(&argc, argv);
208 grpc::testing::TestEnvironment env(argc, argv);
209 return RUN_ALL_TESTS();
210 };
211