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