xref: /aosp_15_r20/external/grpc-grpc/test/core/end2end/tests/compressed_payload.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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