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/compression.h>
20 #include <grpc/grpc.h>
21 #include <grpc/impl/channel_arg_names.h>
22 #include <grpc/status.h>
23 #include <stdint.h>
24
25 #include <initializer_list>
26 #include <string>
27 #include <utility>
28
29 #include "absl/strings/string_view.h"
30 #include "gtest/gtest.h"
31 #include "src/core/lib/channel/channel_args.h"
32 #include "src/core/util/bitset.h"
33 #include "src/core/util/time.h"
34 #include "test/core/end2end/end2end_tests.h"
35
36 namespace grpc_core {
37 namespace {
38
39 class TestConfigurator {
40 public:
TestConfigurator(CoreEnd2endTest & test)41 explicit TestConfigurator(CoreEnd2endTest& test) : test_(test) {}
42
DisableAlgorithmAtServer(grpc_compression_algorithm algorithm)43 TestConfigurator& DisableAlgorithmAtServer(
44 grpc_compression_algorithm algorithm) {
45 server_args_ =
46 server_args_.Set(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET,
47 BitSet<GRPC_COMPRESS_ALGORITHMS_COUNT>()
48 .SetAll(true)
49 .Set(algorithm, false)
50 .ToInt<uint32_t>());
51 return *this;
52 }
53
ClientDefaultAlgorithm(grpc_compression_algorithm algorithm)54 TestConfigurator& ClientDefaultAlgorithm(
55 grpc_compression_algorithm algorithm) {
56 client_args_ =
57 client_args_.Set(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm);
58 return *this;
59 }
60
ServerDefaultAlgorithm(grpc_compression_algorithm algorithm)61 TestConfigurator& ServerDefaultAlgorithm(
62 grpc_compression_algorithm algorithm) {
63 server_args_ =
64 server_args_.Set(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm);
65 return *this;
66 }
67
DecompressInApp()68 TestConfigurator& DecompressInApp() {
69 client_args_ =
70 client_args_.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false);
71 server_args_ =
72 server_args_.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false);
73 return *this;
74 }
75
ExpectedAlgorithmFromClient(grpc_compression_algorithm algorithm)76 TestConfigurator& ExpectedAlgorithmFromClient(
77 grpc_compression_algorithm algorithm) {
78 expected_algorithm_from_client_ = algorithm;
79 return *this;
80 }
81
ExpectedAlgorithmFromServer(grpc_compression_algorithm algorithm)82 TestConfigurator& ExpectedAlgorithmFromServer(
83 grpc_compression_algorithm algorithm) {
84 expected_algorithm_from_server_ = algorithm;
85 return *this;
86 }
87
DisabledAlgorithmTest()88 void DisabledAlgorithmTest() {
89 Init();
90 auto c = test_.NewClientCall("/foo").Timeout(Duration::Minutes(1)).Create();
91 auto s = test_.RequestCall(101);
92 IncomingMetadata server_initial_metadata;
93 IncomingStatusOnClient server_status;
94 c.NewBatch(1)
95 .SendInitialMetadata({})
96 .SendMessage(std::string(1024, 'x'))
97 .SendCloseFromClient()
98 .RecvInitialMetadata(server_initial_metadata)
99 .RecvStatusOnClient(server_status);
100 test_.Expect(101, true);
101 test_.Expect(1, true);
102 test_.Step();
103 IncomingMessage client_message;
104 s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message);
105 IncomingCloseOnServer client_close;
106 test_.Expect(102, false);
107 s.NewBatch(103).RecvCloseOnServer(client_close);
108 test_.Expect(103, true);
109 test_.Step();
110 // call was cancelled (closed) ...
111 EXPECT_NE(client_close.was_cancelled(), 0);
112 // with a certain error
113 EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED);
114 // and we expect a specific reason for it
115 EXPECT_EQ(server_status.message(),
116 "Compression algorithm 'gzip' is disabled.");
117 EXPECT_EQ(s.method(), "/foo");
118 }
119
RequestWithPayload(uint32_t client_send_flags_bitmask,std::initializer_list<std::pair<absl::string_view,absl::string_view>> client_init_metadata)120 void RequestWithPayload(
121 uint32_t client_send_flags_bitmask,
122 std::initializer_list<std::pair<absl::string_view, absl::string_view>>
123 client_init_metadata) {
124 Init();
125 auto c =
126 test_.NewClientCall("/foo").Timeout(Duration::Seconds(30)).Create();
127 IncomingStatusOnClient server_status;
128 IncomingMetadata server_initial_metadata;
129 c.NewBatch(1)
130 .SendInitialMetadata(client_init_metadata)
131 .RecvInitialMetadata(server_initial_metadata)
132 .RecvStatusOnClient(server_status);
133 auto s = test_.RequestCall(100);
134 test_.Expect(100, true);
135 test_.Step();
136 EXPECT_TRUE(s.GetEncodingsAcceptedByPeer().all());
137 IncomingCloseOnServer client_close;
138 s.NewBatch(101).SendInitialMetadata({}).RecvCloseOnServer(client_close);
139 for (int i = 0; i < 2; i++) {
140 c.NewBatch(2).SendMessage(std::string(1024, 'x'),
141 client_send_flags_bitmask);
142 test_.Expect(2, true);
143 IncomingMessage client_message;
144 s.NewBatch(102).RecvMessage(client_message);
145 test_.Expect(102, true);
146 test_.Step();
147 EXPECT_EQ(client_message.byte_buffer_type(), GRPC_BB_RAW);
148 EXPECT_EQ(client_message.payload(), std::string(1024, 'x'));
149 EXPECT_EQ(client_message.compression(), expected_algorithm_from_client_);
150 s.NewBatch(103).SendMessage(std::string(1024, 'y'));
151 IncomingMessage server_message;
152 c.NewBatch(3).RecvMessage(server_message);
153 test_.Expect(103, true);
154 test_.Expect(3, true);
155 test_.Step();
156 EXPECT_EQ(server_message.byte_buffer_type(), GRPC_BB_RAW);
157 EXPECT_EQ(server_message.payload(), std::string(1024, 'y'));
158 EXPECT_EQ(server_message.compression(), expected_algorithm_from_server_);
159 }
160 c.NewBatch(4).SendCloseFromClient();
161 s.NewBatch(104).SendStatusFromServer(GRPC_STATUS_OK, "xyz", {});
162 test_.Expect(1, true);
163 test_.Expect(4, true);
164 test_.Expect(101, true);
165 test_.Expect(104, true);
166 test_.Step();
167 EXPECT_EQ(server_status.status(), GRPC_STATUS_OK);
168 EXPECT_EQ(server_status.message(), "xyz");
169 EXPECT_EQ(s.method(), "/foo");
170 EXPECT_FALSE(client_close.was_cancelled());
171 }
172
RequestWithSendMessageBeforeInitialMetadata()173 void RequestWithSendMessageBeforeInitialMetadata() {
174 Init();
175 auto c =
176 test_.NewClientCall("/foo").Timeout(Duration::Seconds(30)).Create();
177 c.NewBatch(2).SendMessage(std::string(1024, 'x'));
178 test_.Expect(2, true);
179 IncomingStatusOnClient server_status;
180 IncomingMetadata server_initial_metadata;
181 c.NewBatch(1)
182 .SendInitialMetadata({})
183 .RecvInitialMetadata(server_initial_metadata)
184 .RecvStatusOnClient(server_status);
185 auto s = test_.RequestCall(100);
186 test_.Expect(100, true);
187 test_.Step();
188 EXPECT_TRUE(s.GetEncodingsAcceptedByPeer().all());
189 IncomingCloseOnServer client_close;
190 s.NewBatch(101).SendInitialMetadata({}).RecvCloseOnServer(client_close);
191 for (int i = 0; i < 2; i++) {
192 if (i > 0) {
193 c.NewBatch(2).SendMessage(std::string(1024, 'x'));
194 test_.Expect(2, true);
195 }
196 IncomingMessage client_message;
197 s.NewBatch(102).RecvMessage(client_message);
198 test_.Expect(102, true);
199 test_.Step();
200 EXPECT_EQ(client_message.byte_buffer_type(), GRPC_BB_RAW);
201 EXPECT_EQ(client_message.payload(), std::string(1024, 'x'));
202 EXPECT_EQ(client_message.compression(), expected_algorithm_from_client_);
203 s.NewBatch(103).SendMessage(std::string(1024, 'y'));
204 IncomingMessage server_message;
205 c.NewBatch(3).RecvMessage(server_message);
206 test_.Expect(103, true);
207 test_.Expect(3, true);
208 test_.Step();
209 EXPECT_EQ(server_message.byte_buffer_type(), GRPC_BB_RAW);
210 EXPECT_EQ(server_message.payload(), std::string(1024, 'y'));
211 EXPECT_EQ(server_message.compression(), expected_algorithm_from_server_);
212 }
213 c.NewBatch(4).SendCloseFromClient();
214 s.NewBatch(104).SendStatusFromServer(GRPC_STATUS_OK, "xyz", {});
215 test_.Expect(1, true);
216 test_.Expect(4, true);
217 test_.Expect(101, true);
218 test_.Expect(104, true);
219 test_.Step();
220 EXPECT_EQ(server_status.status(), GRPC_STATUS_OK);
221 EXPECT_EQ(server_status.message(), "xyz");
222 EXPECT_EQ(s.method(), "/foo");
223 EXPECT_FALSE(client_close.was_cancelled());
224 }
225
RequestWithServerLevel(grpc_compression_level server_compression_level)226 void RequestWithServerLevel(grpc_compression_level server_compression_level) {
227 Init();
228 auto c = test_.NewClientCall("/foo").Timeout(Duration::Minutes(1)).Create();
229 IncomingStatusOnClient server_status;
230 IncomingMetadata server_initial_metadata;
231 c.NewBatch(1)
232 .SendInitialMetadata({})
233 .RecvInitialMetadata(server_initial_metadata)
234 .RecvStatusOnClient(server_status);
235 auto s = test_.RequestCall(100);
236 test_.Expect(100, true);
237 test_.Step();
238 EXPECT_TRUE(s.GetEncodingsAcceptedByPeer().all());
239 IncomingCloseOnServer client_close;
240 s.NewBatch(101)
241 .SendInitialMetadata({}, 0, server_compression_level)
242 .RecvCloseOnServer(client_close);
243 for (int i = 0; i < 2; i++) {
244 c.NewBatch(2).SendMessage(std::string(1024, 'x'));
245 test_.Expect(2, true);
246 IncomingMessage client_message;
247 s.NewBatch(102).RecvMessage(client_message);
248 test_.Expect(102, true);
249 test_.Step();
250 EXPECT_EQ(client_message.byte_buffer_type(), GRPC_BB_RAW);
251 EXPECT_EQ(client_message.payload(), std::string(1024, 'x'));
252 EXPECT_EQ(client_message.compression(), expected_algorithm_from_client_);
253 s.NewBatch(103).SendMessage(std::string(1024, 'y'));
254 IncomingMessage server_message;
255 c.NewBatch(3).RecvMessage(server_message);
256 test_.Expect(103, true);
257 test_.Expect(3, true);
258 test_.Step();
259 EXPECT_EQ(server_message.byte_buffer_type(), GRPC_BB_RAW);
260 EXPECT_EQ(server_message.payload(), std::string(1024, 'y'));
261 EXPECT_EQ(server_message.compression(), expected_algorithm_from_server_);
262 }
263 c.NewBatch(4).SendCloseFromClient();
264 s.NewBatch(104).SendStatusFromServer(GRPC_STATUS_OK, "xyz", {});
265 test_.Expect(1, true);
266 test_.Expect(4, true);
267 test_.Expect(101, true);
268 test_.Expect(104, true);
269 test_.Step();
270 EXPECT_EQ(server_status.status(), GRPC_STATUS_OK);
271 EXPECT_EQ(server_status.message(), "xyz");
272 EXPECT_EQ(s.method(), "/foo");
273 EXPECT_FALSE(client_close.was_cancelled());
274 }
275
276 private:
Init()277 void Init() {
278 test_.InitClient(client_args_);
279 test_.InitServer(server_args_);
280 }
281
282 CoreEnd2endTest& test_;
283 ChannelArgs client_args_ = ChannelArgs().Set(
284 GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, GRPC_COMPRESS_NONE);
285 ChannelArgs server_args_ = ChannelArgs().Set(
286 GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, GRPC_COMPRESS_NONE);
287 grpc_compression_algorithm expected_algorithm_from_client_ =
288 GRPC_COMPRESS_NONE;
289 grpc_compression_algorithm expected_algorithm_from_server_ =
290 GRPC_COMPRESS_NONE;
291 };
292
CORE_END2END_TEST(Http2SingleHopTest,DisabledAlgorithmDecompressInCore)293 CORE_END2END_TEST(Http2SingleHopTest, DisabledAlgorithmDecompressInCore) {
294 TestConfigurator(*this)
295 .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
296 .DisableAlgorithmAtServer(GRPC_COMPRESS_GZIP)
297 .DisabledAlgorithmTest();
298 }
299
CORE_END2END_TEST(Http2SingleHopTest,DisabledAlgorithmDecompressInApp)300 CORE_END2END_TEST(Http2SingleHopTest, DisabledAlgorithmDecompressInApp) {
301 TestConfigurator(*this)
302 .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
303 .DisableAlgorithmAtServer(GRPC_COMPRESS_GZIP)
304 .DecompressInApp()
305 .DisabledAlgorithmTest();
306 }
307
CORE_END2END_TEST(Http2SingleHopTest,RequestWithExceptionallyUncompressedPayloadDecompressInCore)308 CORE_END2END_TEST(Http2SingleHopTest,
309 RequestWithExceptionallyUncompressedPayloadDecompressInCore) {
310 TestConfigurator(*this)
311 .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
312 .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP)
313 .RequestWithPayload(GRPC_WRITE_NO_COMPRESS, {});
314 }
315
CORE_END2END_TEST(Http2SingleHopTest,RequestWithExceptionallyUncompressedPayloadDecompressInApp)316 CORE_END2END_TEST(Http2SingleHopTest,
317 RequestWithExceptionallyUncompressedPayloadDecompressInApp) {
318 TestConfigurator(*this)
319 .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
320 .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP)
321 .DecompressInApp()
322 .ExpectedAlgorithmFromServer(GRPC_COMPRESS_GZIP)
323 .RequestWithPayload(GRPC_WRITE_NO_COMPRESS, {});
324 }
325
CORE_END2END_TEST(Http2SingleHopTest,RequestWithUncompressedPayloadDecompressInCore)326 CORE_END2END_TEST(Http2SingleHopTest,
327 RequestWithUncompressedPayloadDecompressInCore) {
328 TestConfigurator(*this).RequestWithPayload(0, {});
329 }
330
CORE_END2END_TEST(Http2SingleHopTest,RequestWithUncompressedPayloadDecompressInApp)331 CORE_END2END_TEST(Http2SingleHopTest,
332 RequestWithUncompressedPayloadDecompressInApp) {
333 TestConfigurator(*this).DecompressInApp().RequestWithPayload(0, {});
334 }
335
CORE_END2END_TEST(Http2SingleHopTest,RequestWithCompressedPayloadDecompressInCore)336 CORE_END2END_TEST(Http2SingleHopTest,
337 RequestWithCompressedPayloadDecompressInCore) {
338 TestConfigurator(*this)
339 .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
340 .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP)
341 .RequestWithPayload(0, {});
342 }
343
CORE_END2END_TEST(Http2SingleHopTest,RequestWithCompressedPayloadDecompressInApp)344 CORE_END2END_TEST(Http2SingleHopTest,
345 RequestWithCompressedPayloadDecompressInApp) {
346 TestConfigurator(*this)
347 .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
348 .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP)
349 .DecompressInApp()
350 .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP)
351 .ExpectedAlgorithmFromServer(GRPC_COMPRESS_GZIP)
352 .RequestWithPayload(0, {});
353 }
354
CORE_END2END_TEST(Http2SingleHopTest,RequestWithSendMessageBeforeInitialMetadataDecompressInCore)355 CORE_END2END_TEST(Http2SingleHopTest,
356 RequestWithSendMessageBeforeInitialMetadataDecompressInCore) {
357 TestConfigurator(*this)
358 .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
359 .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP)
360 .RequestWithSendMessageBeforeInitialMetadata();
361 }
362
CORE_END2END_TEST(Http2SingleHopTest,RequestWithSendMessageBeforeInitialMetadataDecompressInApp)363 CORE_END2END_TEST(Http2SingleHopTest,
364 RequestWithSendMessageBeforeInitialMetadataDecompressInApp) {
365 TestConfigurator(*this)
366 .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
367 .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP)
368 .DecompressInApp()
369 .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP)
370 .ExpectedAlgorithmFromServer(GRPC_COMPRESS_GZIP)
371 .RequestWithSendMessageBeforeInitialMetadata();
372 }
373
CORE_END2END_TEST(Http2SingleHopTest,RequestWithServerLevelDecompressInCore)374 CORE_END2END_TEST(Http2SingleHopTest, RequestWithServerLevelDecompressInCore) {
375 TestConfigurator(*this).RequestWithServerLevel(GRPC_COMPRESS_LEVEL_HIGH);
376 }
377
CORE_END2END_TEST(Http2SingleHopTest,RequestWithServerLevelDecompressInApp)378 CORE_END2END_TEST(Http2SingleHopTest, RequestWithServerLevelDecompressInApp) {
379 TestConfigurator(*this)
380 .DecompressInApp()
381 .ExpectedAlgorithmFromServer(GRPC_COMPRESS_DEFLATE)
382 .RequestWithServerLevel(GRPC_COMPRESS_LEVEL_HIGH);
383 }
384
CORE_END2END_TEST(Http2SingleHopTest,RequestWithCompressedPayloadMetadataOverrideNoneToGzipDecompressInCore)385 CORE_END2END_TEST(
386 Http2SingleHopTest,
387 RequestWithCompressedPayloadMetadataOverrideNoneToGzipDecompressInCore) {
388 TestConfigurator(*this).RequestWithPayload(
389 0, {{"grpc-internal-encoding-request", "gzip"}});
390 }
391
CORE_END2END_TEST(Http2SingleHopTest,RequestWithCompressedPayloadMetadataOverrideNoneToGzipDecompressInApp)392 CORE_END2END_TEST(
393 Http2SingleHopTest,
394 RequestWithCompressedPayloadMetadataOverrideNoneToGzipDecompressInApp) {
395 TestConfigurator(*this)
396 .DecompressInApp()
397 .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP)
398 .RequestWithPayload(0, {{"grpc-internal-encoding-request", "gzip"}});
399 }
400
CORE_END2END_TEST(Http2SingleHopTest,RequestWithCompressedPayloadMetadataOverrideDeflateToGzipDecompressInCore)401 CORE_END2END_TEST(
402 Http2SingleHopTest,
403 RequestWithCompressedPayloadMetadataOverrideDeflateToGzipDecompressInCore) {
404 TestConfigurator(*this)
405 .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE)
406 .RequestWithPayload(0, {{"grpc-internal-encoding-request", "gzip"}});
407 }
408
CORE_END2END_TEST(Http2SingleHopTest,RequestWithCompressedPayloadMetadataOverrideDeflateToGzipDecompressInApp)409 CORE_END2END_TEST(
410 Http2SingleHopTest,
411 RequestWithCompressedPayloadMetadataOverrideDeflateToGzipDecompressInApp) {
412 TestConfigurator(*this)
413 .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE)
414 .DecompressInApp()
415 .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP)
416 .RequestWithPayload(0, {{"grpc-internal-encoding-request", "gzip"}});
417 }
418
CORE_END2END_TEST(Http2SingleHopTest,RequestWithCompressedPayloadMetadataOverrideDeflateToIdentityDecompressInCore)419 CORE_END2END_TEST(
420 Http2SingleHopTest,
421 RequestWithCompressedPayloadMetadataOverrideDeflateToIdentityDecompressInCore) {
422 TestConfigurator(*this)
423 .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE)
424 .RequestWithPayload(0, {{"grpc-internal-encoding-request", "identity"}});
425 }
426
CORE_END2END_TEST(Http2SingleHopTest,RequestWithCompressedPayloadMetadataOverrideDeflateToIdentityDecompressInApp)427 CORE_END2END_TEST(
428 Http2SingleHopTest,
429 RequestWithCompressedPayloadMetadataOverrideDeflateToIdentityDecompressInApp) {
430 TestConfigurator(*this)
431 .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE)
432 .DecompressInApp()
433 .RequestWithPayload(0, {{"grpc-internal-encoding-request", "identity"}});
434 }
435
436 } // namespace
437 } // namespace grpc_core
438