• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include <stdio.h>
20 
21 #include <string>
22 
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 
26 #include <grpc/impl/channel_arg_names.h>
27 #include <grpc/status.h>
28 
29 #include "src/core/lib/channel/channel_args.h"
30 #include "src/core/lib/gprpp/time.h"
31 #include "test/core/end2end/end2end_tests.h"
32 
33 namespace grpc_core {
34 namespace {
35 
36 class LargeMetadataTest {
37  public:
LargeMetadataTest(Http2SingleHopTest & test,const ChannelArgs & args)38   LargeMetadataTest(Http2SingleHopTest& test, const ChannelArgs& args)
39       : test_(test) {
40     test_.InitClient(args);
41     test_.InitServer(args);
42   }
43 
PerformRequests(size_t metadata_size,int count)44   int PerformRequests(size_t metadata_size, int count) {
45     int num_requests_accepted = 0;
46     for (int i = 0; i < count; ++i) {
47       auto status = PerformOneRequest(metadata_size);
48       if (status.status() == GRPC_STATUS_RESOURCE_EXHAUSTED) {
49         EXPECT_THAT(status.message(),
50                     ::testing::StartsWith("received metadata size exceeds"));
51       } else {
52         num_requests_accepted++;
53         EXPECT_EQ(status.status(), GRPC_STATUS_OK);
54         EXPECT_EQ(status.message(), "xyz");
55       }
56     }
57     return num_requests_accepted;
58   }
59 
60  private:
PerformOneRequest(const size_t metadata_size)61   CoreEnd2endTest::IncomingStatusOnClient PerformOneRequest(
62       const size_t metadata_size) {
63     auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
64     CoreEnd2endTest::IncomingMetadata server_initial_metadata;
65     CoreEnd2endTest::IncomingStatusOnClient server_status;
66     c.NewBatch(1)
67         .SendInitialMetadata({})
68         .SendCloseFromClient()
69         .RecvInitialMetadata(server_initial_metadata)
70         .RecvStatusOnClient(server_status);
71     auto s = test_.RequestCall(101);
72     test_.Expect(101, true);
73     test_.Step();
74     // Server: send metadata of size `metadata_size`.
75     CoreEnd2endTest::IncomingCloseOnServer client_close;
76     s.NewBatch(102)
77         .SendInitialMetadata({{"key", std::string(metadata_size, 'a')}})
78         .RecvCloseOnServer(client_close)
79         .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {});
80     test_.Expect(102, true);
81     test_.Expect(1, true);
82     test_.Step();
83     return server_status;
84   }
85 
86   Http2SingleHopTest& test_;
87 };
88 
89 // Server responds with metadata under soft limit of what client accepts. No
90 // requests should be rejected.
CORE_END2END_TEST(Http2SingleHopTest,RequestWithLargeMetadataUnderSoftLimit)91 CORE_END2END_TEST(Http2SingleHopTest, RequestWithLargeMetadataUnderSoftLimit) {
92   const size_t soft_limit = 32 * 1024;
93   const size_t hard_limit = 45 * 1024;
94   const size_t metadata_size = soft_limit;
95   LargeMetadataTest test(
96       *this, ChannelArgs()
97                  .Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024)
98                  .Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, hard_limit + 1024));
99   EXPECT_EQ(test.PerformRequests(metadata_size, 100), 100);
100 }
101 
102 // Server responds with metadata between soft and hard limits of what client
103 // accepts. Some requests should be rejected.
CORE_END2END_TEST(Http2SingleHopTest,RequestWithLargeMetadataBetweenSoftAndHardLimits)104 CORE_END2END_TEST(Http2SingleHopTest,
105                   RequestWithLargeMetadataBetweenSoftAndHardLimits) {
106   const size_t soft_limit = 32 * 1024;
107   const size_t hard_limit = 45 * 1024;
108   const size_t metadata_size = (soft_limit + hard_limit) / 2;
109   LargeMetadataTest test(
110       *this, ChannelArgs()
111                  .Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024)
112                  .Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, hard_limit + 1024));
113   EXPECT_THAT(test.PerformRequests(metadata_size, 100),
114               ::testing::AllOf(::testing::Ge(5), ::testing::Le(95)));
115 }
116 
117 // Server responds with metadata above hard limit of what the client accepts.
118 // All requests should be rejected.
CORE_END2END_TEST(Http2SingleHopTest,RequestWithLargeMetadataAboveHardLimit)119 CORE_END2END_TEST(Http2SingleHopTest, RequestWithLargeMetadataAboveHardLimit) {
120   const size_t soft_limit = 32 * 1024;
121   const size_t hard_limit = 45 * 1024;
122   const size_t metadata_size = hard_limit * 3 / 2;
123   LargeMetadataTest test(
124       *this, ChannelArgs()
125                  .Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024)
126                  .Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, hard_limit + 1024));
127   EXPECT_EQ(test.PerformRequests(metadata_size, 100), 0);
128 }
129 
130 // Set soft limit higher than hard limit. All requests above hard limit should
131 // be rejected, all requests below hard limit should be accepted (soft limit
132 // should not be respected).
CORE_END2END_TEST(Http2SingleHopTest,RequestWithLargeMetadataSoftLimitAboveHardLimit)133 CORE_END2END_TEST(Http2SingleHopTest,
134                   RequestWithLargeMetadataSoftLimitAboveHardLimit) {
135   const size_t soft_limit = 64 * 1024;
136   const size_t hard_limit = 32 * 1024;
137   const size_t metadata_size_below_hard_limit = hard_limit;
138   const size_t metadata_size_above_hard_limit = hard_limit * 2;
139   LargeMetadataTest test(
140       *this, ChannelArgs()
141                  .Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024)
142                  .Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, hard_limit + 1024));
143   // Send 50 requests below hard limit. Should be accepted.
144   EXPECT_EQ(test.PerformRequests(metadata_size_below_hard_limit, 50), 50);
145   // Send 50 requests above hard limit. Should be rejected.
146   EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0);
147 }
148 
149 // Set soft limit * 1.25 higher than default hard limit and do not set hard
150 // limit. Soft limit * 1.25 should be used as hard limit.
CORE_END2END_TEST(Http2SingleHopTest,RequestWithLargeMetadataSoftLimitOverridesDefaultHard)151 CORE_END2END_TEST(Http2SingleHopTest,
152                   RequestWithLargeMetadataSoftLimitOverridesDefaultHard) {
153   const size_t soft_limit = 64 * 1024;
154   const size_t metadata_size_below_soft_limit = soft_limit;
155   const size_t metadata_size_above_hard_limit = soft_limit * 1.5;
156   const size_t metadata_size_between_limits =
157       (soft_limit + soft_limit * 1.25) / 2;
158   LargeMetadataTest test(
159       *this, ChannelArgs().Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024));
160   // Send 50 requests below soft limit. Should be accepted.
161   EXPECT_EQ(test.PerformRequests(metadata_size_below_soft_limit, 50), 50);
162   // Send 100 requests between soft and hard limits. Some should be rejected.
163   EXPECT_THAT(test.PerformRequests(metadata_size_between_limits, 100),
164               ::testing::AllOf(::testing::Ge(5), ::testing::Le(95)));
165   // Send 50 requests above hard limit. Should be rejected.
166   EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0);
167 }
168 
169 // Set hard limit * 0.8 higher than default soft limit and do not set soft
170 // limit. Hard limit * 0.8 should be used as soft limit.
CORE_END2END_TEST(Http2SingleHopTest,RequestWithLargeMetadataHardLimitOverridsDefaultSoft)171 CORE_END2END_TEST(Http2SingleHopTest,
172                   RequestWithLargeMetadataHardLimitOverridsDefaultSoft) {
173   const size_t hard_limit = 45 * 1024;
174   const size_t metadata_size_below_soft_limit = hard_limit * 0.5;
175   const size_t metadata_size_above_hard_limit = hard_limit * 1.5;
176   const size_t metadata_size_between_limits =
177       (hard_limit * 0.8 + hard_limit) / 2;
178   LargeMetadataTest test(*this,
179                          ChannelArgs().Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE,
180                                            hard_limit + 1024));
181   // Send 50 requests below soft limit. Should be accepted.
182   EXPECT_EQ(test.PerformRequests(metadata_size_below_soft_limit, 50), 50);
183   // Send 100 requests between soft and hard limits. Some should be rejected.
184   EXPECT_THAT(test.PerformRequests(metadata_size_between_limits, 100),
185               ::testing::AllOf(::testing::Ge(5), ::testing::Le(95)));
186   // Send 50 requests above hard limit. Should be rejected.
187   EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0);
188 }
189 
190 // Set hard limit lower than default hard limit and ensure new limit is
191 // respected. Default soft limit is not respected since hard limit is lower than
192 // soft limit.
CORE_END2END_TEST(Http2SingleHopTest,RequestWithLargeMetadataHardLimitBelowDefaultHard)193 CORE_END2END_TEST(Http2SingleHopTest,
194                   RequestWithLargeMetadataHardLimitBelowDefaultHard) {
195   const size_t hard_limit = 4 * 1024;
196   const size_t metadata_size_below_hard_limit = hard_limit;
197   const size_t metadata_size_above_hard_limit = hard_limit * 2;
198   LargeMetadataTest test(*this,
199                          ChannelArgs().Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE,
200                                            hard_limit + 1024));
201   // Send 50 requests below hard limit. Should be accepted.
202   EXPECT_EQ(test.PerformRequests(metadata_size_below_hard_limit, 50), 50);
203   // Send 50 requests above hard limit. Should be rejected.
204   EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0);
205 }
206 
207 // Set soft limit lower than default soft limit and ensure new limit is
208 // respected. Hard limit should be default hard since this is greater than 2 *
209 // soft limit.
CORE_END2END_TEST(Http2SingleHopTest,RequestWithLargeMetadataSoftLimitBelowDefaultSoft)210 CORE_END2END_TEST(Http2SingleHopTest,
211                   RequestWithLargeMetadataSoftLimitBelowDefaultSoft) {
212   const size_t soft_limit = 1 * 1024;
213   const size_t metadata_size_below_soft_limit = soft_limit;
214   // greater than 2 * soft, less than default hard
215   const size_t metadata_size_between_limits = 10 * 1024;
216   const size_t metadata_size_above_hard_limit = 75 * 1024;
217   LargeMetadataTest test(
218       *this, ChannelArgs().Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024));
219   // Send 50 requests below soft limit. Should be accepted.
220   EXPECT_EQ(test.PerformRequests(metadata_size_below_soft_limit, 50), 50);
221   // Send 100 requests between soft and hard limits. Some should be rejected.
222   EXPECT_THAT(test.PerformRequests(metadata_size_between_limits, 100),
223               ::testing::AllOf(::testing::Ge(1), ::testing::Le(99)));
224   // Send 50 requests above hard limit. Should be rejected.
225   EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0);
226 }
227 
228 }  // namespace
229 }  // namespace grpc_core
230