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