xref: /aosp_15_r20/external/grpc-grpc/test/core/transport/metadata_map_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 <stdlib.h>
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "absl/strings/match.h"
24 #include "absl/strings/str_cat.h"
25 #include "absl/strings/str_split.h"
26 #include "absl/types/optional.h"
27 #include "gtest/gtest.h"
28 
29 #include <grpc/event_engine/memory_allocator.h>
30 
31 #include "src/core/lib/gprpp/ref_counted_ptr.h"
32 #include "src/core/lib/gprpp/time.h"
33 #include "src/core/lib/resource_quota/arena.h"
34 #include "src/core/lib/resource_quota/memory_quota.h"
35 #include "src/core/lib/resource_quota/resource_quota.h"
36 #include "src/core/lib/slice/slice.h"
37 #include "src/core/lib/transport/metadata_batch.h"
38 #include "test/core/util/test_config.h"
39 
40 namespace grpc_core {
41 namespace testing {
42 
43 struct EmptyMetadataMap : public MetadataMap<EmptyMetadataMap> {
44   using MetadataMap<EmptyMetadataMap>::MetadataMap;
45 };
46 
47 struct TimeoutOnlyMetadataMap
48     : public MetadataMap<TimeoutOnlyMetadataMap, GrpcTimeoutMetadata> {
49   using MetadataMap<TimeoutOnlyMetadataMap, GrpcTimeoutMetadata>::MetadataMap;
50 };
51 
52 struct StreamNetworkStateMetadataMap
53     : public MetadataMap<StreamNetworkStateMetadataMap,
54                          GrpcStreamNetworkState> {
55   using MetadataMap<StreamNetworkStateMetadataMap,
56                     GrpcStreamNetworkState>::MetadataMap;
57 };
58 
59 class MetadataMapTest : public ::testing::Test {
60  protected:
61   MemoryAllocator memory_allocator_ = MemoryAllocator(
62       ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
63 };
64 
TEST_F(MetadataMapTest,Noop)65 TEST_F(MetadataMapTest, Noop) {
66   auto arena = MakeScopedArena(1024, &memory_allocator_);
67   EmptyMetadataMap();
68 }
69 
TEST_F(MetadataMapTest,NoopWithDeadline)70 TEST_F(MetadataMapTest, NoopWithDeadline) {
71   auto arena = MakeScopedArena(1024, &memory_allocator_);
72   TimeoutOnlyMetadataMap();
73 }
74 
TEST_F(MetadataMapTest,SimpleOps)75 TEST_F(MetadataMapTest, SimpleOps) {
76   auto arena = MakeScopedArena(1024, &memory_allocator_);
77   TimeoutOnlyMetadataMap map;
78   EXPECT_EQ(map.get_pointer(GrpcTimeoutMetadata()), nullptr);
79   EXPECT_EQ(map.get(GrpcTimeoutMetadata()), absl::nullopt);
80   map.Set(GrpcTimeoutMetadata(),
81           Timestamp::FromMillisecondsAfterProcessEpoch(1234));
82   EXPECT_NE(map.get_pointer(GrpcTimeoutMetadata()), nullptr);
83   EXPECT_EQ(*map.get_pointer(GrpcTimeoutMetadata()),
84             Timestamp::FromMillisecondsAfterProcessEpoch(1234));
85   EXPECT_EQ(map.get(GrpcTimeoutMetadata()),
86             Timestamp::FromMillisecondsAfterProcessEpoch(1234));
87   map.Remove(GrpcTimeoutMetadata());
88   EXPECT_EQ(map.get_pointer(GrpcTimeoutMetadata()), nullptr);
89   EXPECT_EQ(map.get(GrpcTimeoutMetadata()), absl::nullopt);
90 }
91 
92 // Target for MetadataMap::Encode.
93 // Writes down some string representation of what it receives, so we can
94 // EXPECT_EQ it later.
95 class FakeEncoder {
96  public:
output()97   std::string output() { return output_; }
98 
Encode(const Slice & key,const Slice & value)99   void Encode(const Slice& key, const Slice& value) {
100     output_ += absl::StrCat("UNKNOWN METADATUM: key=", key.as_string_view(),
101                             " value=", value.as_string_view(), "\n");
102   }
103 
Encode(GrpcTimeoutMetadata,Timestamp deadline)104   void Encode(GrpcTimeoutMetadata, Timestamp deadline) {
105     output_ += absl::StrCat("grpc-timeout: deadline=",
106                             deadline.milliseconds_after_process_epoch(), "\n");
107   }
108 
109  private:
110   std::string output_;
111 };
112 
TEST_F(MetadataMapTest,EmptyEncodeTest)113 TEST_F(MetadataMapTest, EmptyEncodeTest) {
114   FakeEncoder encoder;
115   auto arena = MakeScopedArena(1024, &memory_allocator_);
116   TimeoutOnlyMetadataMap map;
117   map.Encode(&encoder);
118   EXPECT_EQ(encoder.output(), "");
119 }
120 
TEST_F(MetadataMapTest,TimeoutEncodeTest)121 TEST_F(MetadataMapTest, TimeoutEncodeTest) {
122   FakeEncoder encoder;
123   auto arena = MakeScopedArena(1024, &memory_allocator_);
124   TimeoutOnlyMetadataMap map;
125   map.Set(GrpcTimeoutMetadata(),
126           Timestamp::FromMillisecondsAfterProcessEpoch(1234));
127   map.Encode(&encoder);
128   EXPECT_EQ(encoder.output(), "grpc-timeout: deadline=1234\n");
129 }
130 
TEST_F(MetadataMapTest,NonEncodableTrait)131 TEST_F(MetadataMapTest, NonEncodableTrait) {
132   struct EncoderWithNoTraitEncodeFunctions {
133     void Encode(const Slice&, const Slice&) {
134       abort();  // should not be called
135     }
136   };
137   auto arena = MakeScopedArena(1024, &memory_allocator_);
138   StreamNetworkStateMetadataMap map;
139   map.Set(GrpcStreamNetworkState(), GrpcStreamNetworkState::kNotSentOnWire);
140   EXPECT_EQ(map.get(GrpcStreamNetworkState()),
141             GrpcStreamNetworkState::kNotSentOnWire);
142   EncoderWithNoTraitEncodeFunctions encoder;
143   map.Encode(&encoder);
144   EXPECT_EQ(map.DebugString(), "GrpcStreamNetworkState: not sent on wire");
145 }
146 
TEST(DebugStringBuilderTest,OneAddAfterRedaction)147 TEST(DebugStringBuilderTest, OneAddAfterRedaction) {
148   metadata_detail::DebugStringBuilder b;
149   b.AddAfterRedaction(ContentTypeMetadata::key(), "AddValue01");
150   EXPECT_EQ(b.TakeOutput(),
151             absl::StrCat(ContentTypeMetadata::key(), ": AddValue01"));
152 }
153 
GetAllowList()154 std::vector<std::string> GetAllowList() {
155   return {
156       // clang-format off
157           std::string(ContentTypeMetadata::key()),
158           std::string(EndpointLoadMetricsBinMetadata::key()),
159           std::string(GrpcAcceptEncodingMetadata::key()),
160           std::string(GrpcEncodingMetadata::key()),
161           std::string(GrpcInternalEncodingRequest::key()),
162           std::string(GrpcLbClientStatsMetadata::key()),
163           std::string(GrpcMessageMetadata::key()),
164           std::string(GrpcPreviousRpcAttemptsMetadata::key()),
165           std::string(GrpcRetryPushbackMsMetadata::key()),
166           std::string(GrpcServerStatsBinMetadata::key()),
167           std::string(GrpcStatusMetadata::key()),
168           std::string(GrpcTagsBinMetadata::key()),
169           std::string(GrpcTimeoutMetadata::key()),
170           std::string(GrpcTraceBinMetadata::key()),
171           std::string(HostMetadata::key()),
172           std::string(HttpAuthorityMetadata::key()),
173           std::string(HttpMethodMetadata::key()),
174           std::string(HttpPathMetadata::key()),
175           std::string(HttpSchemeMetadata::key()),
176           std::string(HttpStatusMetadata::key()),
177           std::string(LbCostBinMetadata::key()),
178           std::string(LbTokenMetadata::key()),
179           std::string(TeMetadata::key()),
180           std::string(UserAgentMetadata::key()),
181           std::string(XEnvoyPeerMetadata::key()),
182           std::string(GrpcCallWasCancelled::DebugKey()),
183           std::string(GrpcRegisteredMethod::DebugKey()),
184           std::string(GrpcStatusContext::DebugKey()),
185           std::string(GrpcStatusFromWire::DebugKey()),
186           std::string(GrpcStreamNetworkState::DebugKey()),
187           std::string(GrpcTarPit::DebugKey()),
188           std::string(GrpcTrailersOnly::DebugKey()),
189           std::string(PeerString::DebugKey()),
190           std::string(WaitForReady::DebugKey())
191       // clang-format on
192   };
193 }
194 
TEST(DebugStringBuilderTest,TestAllAllowListed)195 TEST(DebugStringBuilderTest, TestAllAllowListed) {
196   metadata_detail::DebugStringBuilder builder_add_allow_list;
197   const std::vector<std::string> allow_list_keys = GetAllowList();
198 
199   for (const std::string& curr_key : allow_list_keys) {
200     builder_add_allow_list.AddAfterRedaction(curr_key, curr_key);
201   }
202 
203   // All values which are allow listed should be added as is.
204   EXPECT_EQ(builder_add_allow_list.TakeOutput(),
205             "content-type: content-type, "
206             "endpoint-load-metrics-bin: endpoint-load-metrics-bin, "
207             "grpc-accept-encoding: grpc-accept-encoding, "
208             "grpc-encoding: grpc-encoding, "
209             "grpc-internal-encoding-request: grpc-internal-encoding-request, "
210             "grpclb_client_stats: grpclb_client_stats, "
211             "grpc-message: grpc-message, "
212             "grpc-previous-rpc-attempts: grpc-previous-rpc-attempts, "
213             "grpc-retry-pushback-ms: grpc-retry-pushback-ms, "
214             "grpc-server-stats-bin: grpc-server-stats-bin, "
215             "grpc-status: grpc-status, "
216             "grpc-tags-bin: grpc-tags-bin, "
217             "grpc-timeout: grpc-timeout, "
218             "grpc-trace-bin: grpc-trace-bin, "
219             "host: host, :authority: :authority, "
220             ":method: :method, "
221             ":path: :path, "
222             ":scheme: :scheme, "
223             ":status: :status, "
224             "lb-cost-bin: lb-cost-bin, "
225             "lb-token: lb-token, "
226             "te: te, "
227             "user-agent: user-agent, "
228             "x-envoy-peer-metadata: x-envoy-peer-metadata, "
229             "GrpcCallWasCancelled: GrpcCallWasCancelled, "
230             "GrpcRegisteredMethod: GrpcRegisteredMethod, "
231             "GrpcStatusContext: GrpcStatusContext, "
232             "GrpcStatusFromWire: GrpcStatusFromWire, "
233             "GrpcStreamNetworkState: GrpcStreamNetworkState, "
234             "GrpcTarPit: GrpcTarPit, "
235             "GrpcTrailersOnly: GrpcTrailersOnly, "
236             "PeerString: PeerString, "
237             "WaitForReady: WaitForReady");
238 }
239 
TEST(DebugStringBuilderTest,TestAllRedacted)240 TEST(DebugStringBuilderTest, TestAllRedacted) {
241   metadata_detail::DebugStringBuilder builder_add_redacted;
242   const std::vector<std::string> allow_list_keys = GetAllowList();
243 
244   for (const std::string& curr_key : allow_list_keys) {
245     builder_add_redacted.AddAfterRedaction(curr_key + "1234", curr_key);
246   }
247 
248   // All values which are not allow listed should be redacted
249   std::vector<std::string> redacted_output =
250       absl::StrSplit(builder_add_redacted.TakeOutput(), ',');
251   int i = 0;
252   for (std::string& curr_row : redacted_output) {
253     std::string redacted_str = absl::StrCat(
254         allow_list_keys[i++].size(), " bytes redacted by allow listing.");
255     EXPECT_EQ(absl::StrContains(curr_row, redacted_str), true);
256   }
257 }
258 
259 }  // namespace testing
260 }  // namespace grpc_core
261 
main(int argc,char ** argv)262 int main(int argc, char** argv) {
263   testing::InitGoogleTest(&argc, argv);
264   grpc::testing::TestEnvironment env(&argc, argv);
265   return RUN_ALL_TESTS();
266 };
267