• 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 "test/core/end2end/end2end_tests.h"
20 
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include <grpc/byte_buffer.h>
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
27 #include <grpc/support/time.h>
28 
29 #include "src/core/lib/channel/channel_args.h"
30 #include "src/core/lib/iomgr/exec_ctx.h"
31 #include "src/core/lib/slice/slice_internal.h"
32 #include "src/core/lib/transport/metadata.h"
33 #include "src/core/lib/transport/service_config.h"
34 
35 #include "test/core/end2end/cq_verifier.h"
36 
tag(intptr_t t)37 static void* tag(intptr_t t) { return (void*)t; }
38 
begin_test(grpc_end2end_test_config config,const char * test_name,grpc_channel_args * client_args,grpc_channel_args * server_args)39 static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
40                                             const char* test_name,
41                                             grpc_channel_args* client_args,
42                                             grpc_channel_args* server_args) {
43   grpc_end2end_test_fixture f;
44   gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
45   // We intentionally do not pass the client and server args to
46   // create_fixture(), since we don't want the limit enforced on the
47   // proxy, only on the backend server.
48   f = config.create_fixture(nullptr, nullptr);
49   config.init_server(&f, server_args);
50   config.init_client(&f, client_args);
51   return f;
52 }
53 
n_seconds_from_now(int n)54 static gpr_timespec n_seconds_from_now(int n) {
55   return grpc_timeout_seconds_to_deadline(n);
56 }
57 
five_seconds_from_now(void)58 static gpr_timespec five_seconds_from_now(void) {
59   return n_seconds_from_now(5);
60 }
61 
drain_cq(grpc_completion_queue * cq)62 static void drain_cq(grpc_completion_queue* cq) {
63   grpc_event ev;
64   do {
65     ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
66   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
67 }
68 
shutdown_server(grpc_end2end_test_fixture * f)69 static void shutdown_server(grpc_end2end_test_fixture* f) {
70   if (!f->server) return;
71   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
72   grpc_event ev = grpc_completion_queue_next(
73       f->cq, grpc_timeout_seconds_to_deadline(5), nullptr);
74   GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
75   GPR_ASSERT(ev.tag == tag(1000));
76   grpc_server_destroy(f->server);
77   f->server = nullptr;
78 }
79 
shutdown_client(grpc_end2end_test_fixture * f)80 static void shutdown_client(grpc_end2end_test_fixture* f) {
81   if (!f->client) return;
82   grpc_channel_destroy(f->client);
83   f->client = nullptr;
84 }
85 
end_test(grpc_end2end_test_fixture * f)86 static void end_test(grpc_end2end_test_fixture* f) {
87   shutdown_server(f);
88   shutdown_client(f);
89 
90   grpc_completion_queue_shutdown(f->cq);
91   drain_cq(f->cq);
92   grpc_completion_queue_destroy(f->cq);
93   grpc_completion_queue_destroy(f->shutdown_cq);
94 }
95 
96 // Test with request larger than the limit.
97 // If send_limit is true, applies send limit on client; otherwise, applies
98 // recv limit on server.
test_max_message_length_on_request(grpc_end2end_test_config config,bool send_limit,bool use_service_config,bool use_string_json_value)99 static void test_max_message_length_on_request(grpc_end2end_test_config config,
100                                                bool send_limit,
101                                                bool use_service_config,
102                                                bool use_string_json_value) {
103   gpr_log(GPR_INFO,
104           "testing request with send_limit=%d use_service_config=%d "
105           "use_string_json_value=%d",
106           send_limit, use_service_config, use_string_json_value);
107 
108   grpc_end2end_test_fixture f;
109   grpc_call* c = nullptr;
110   grpc_call* s = nullptr;
111   cq_verifier* cqv;
112   grpc_op ops[6];
113   grpc_op* op;
114   grpc_slice request_payload_slice =
115       grpc_slice_from_copied_string("hello world");
116   grpc_byte_buffer* request_payload =
117       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
118   grpc_byte_buffer* recv_payload = nullptr;
119   grpc_metadata_array initial_metadata_recv;
120   grpc_metadata_array trailing_metadata_recv;
121   grpc_metadata_array request_metadata_recv;
122   grpc_call_details call_details;
123   grpc_status_code status;
124   grpc_call_error error;
125   grpc_slice details;
126   int was_cancelled = 2;
127 
128   grpc_channel_args* client_args = nullptr;
129   grpc_channel_args* server_args = nullptr;
130   if (use_service_config) {
131     // We don't currently support service configs on the server side.
132     GPR_ASSERT(send_limit);
133     grpc_arg arg;
134     arg.type = GRPC_ARG_STRING;
135     arg.key = const_cast<char*>(GRPC_ARG_SERVICE_CONFIG);
136     arg.value.string =
137         use_string_json_value
138             ? const_cast<char*>(
139                   "{\n"
140                   "  \"methodConfig\": [ {\n"
141                   "    \"name\": [\n"
142                   "      { \"service\": \"service\", \"method\": \"method\" }\n"
143                   "    ],\n"
144                   "    \"maxRequestMessageBytes\": \"5\"\n"
145                   "  } ]\n"
146                   "}")
147             : const_cast<char*>(
148                   "{\n"
149                   "  \"methodConfig\": [ {\n"
150                   "    \"name\": [\n"
151                   "      { \"service\": \"service\", \"method\": \"method\" }\n"
152                   "    ],\n"
153                   "    \"maxRequestMessageBytes\": 5\n"
154                   "  } ]\n"
155                   "}");
156     client_args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
157   } else {
158     // Set limit via channel args.
159     grpc_arg arg;
160     arg.key = send_limit
161                   ? const_cast<char*>(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH)
162                   : const_cast<char*>(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH);
163     arg.type = GRPC_ARG_INTEGER;
164     arg.value.integer = 5;
165     grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
166     if (send_limit) {
167       client_args = args;
168     } else {
169       server_args = args;
170     }
171   }
172 
173   f = begin_test(config, "test_max_request_message_length", client_args,
174                  server_args);
175   {
176     grpc_core::ExecCtx exec_ctx;
177     if (client_args != nullptr) grpc_channel_args_destroy(client_args);
178     if (server_args != nullptr) grpc_channel_args_destroy(server_args);
179   }
180 
181   cqv = cq_verifier_create(f.cq);
182 
183   c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
184                                grpc_slice_from_static_string("/service/method"),
185                                nullptr, gpr_inf_future(GPR_CLOCK_REALTIME),
186                                nullptr);
187   GPR_ASSERT(c);
188 
189   grpc_metadata_array_init(&initial_metadata_recv);
190   grpc_metadata_array_init(&trailing_metadata_recv);
191   grpc_metadata_array_init(&request_metadata_recv);
192   grpc_call_details_init(&call_details);
193 
194   memset(ops, 0, sizeof(ops));
195   op = ops;
196   op->op = GRPC_OP_SEND_INITIAL_METADATA;
197   op->data.send_initial_metadata.count = 0;
198   op->flags = 0;
199   op->reserved = nullptr;
200   op++;
201   op->op = GRPC_OP_SEND_MESSAGE;
202   op->data.send_message.send_message = request_payload;
203   op->flags = 0;
204   op->reserved = nullptr;
205   op++;
206   op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
207   op->flags = 0;
208   op->reserved = nullptr;
209   op++;
210   op->op = GRPC_OP_RECV_INITIAL_METADATA;
211   op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
212   op->flags = 0;
213   op->reserved = nullptr;
214   op++;
215   op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
216   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
217   op->data.recv_status_on_client.status = &status;
218   op->data.recv_status_on_client.status_details = &details;
219   op->flags = 0;
220   op->reserved = nullptr;
221   op++;
222   error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
223                                 nullptr);
224   GPR_ASSERT(GRPC_CALL_OK == error);
225 
226   if (send_limit) {
227     CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
228     cq_verify(cqv);
229     goto done;
230   }
231 
232   error =
233       grpc_server_request_call(f.server, &s, &call_details,
234                                &request_metadata_recv, f.cq, f.cq, tag(101));
235   GPR_ASSERT(GRPC_CALL_OK == error);
236   CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
237   cq_verify(cqv);
238 
239   memset(ops, 0, sizeof(ops));
240   op = ops;
241   op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
242   op->data.recv_close_on_server.cancelled = &was_cancelled;
243   op->flags = 0;
244   op->reserved = nullptr;
245   op++;
246   op->op = GRPC_OP_RECV_MESSAGE;
247   op->data.recv_message.recv_message = &recv_payload;
248   op->flags = 0;
249   op->reserved = nullptr;
250   op++;
251   error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
252                                 nullptr);
253   GPR_ASSERT(GRPC_CALL_OK == error);
254 
255   CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
256   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
257   cq_verify(cqv);
258 
259   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
260   GPR_ASSERT(was_cancelled == 1);
261 
262 done:
263   GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED);
264   GPR_ASSERT(
265       grpc_slice_str_cmp(
266           details, send_limit
267                        ? "Sent message larger than max (11 vs. 5)"
268                        : "Received message larger than max (11 vs. 5)") == 0);
269 
270   grpc_slice_unref(details);
271   grpc_metadata_array_destroy(&initial_metadata_recv);
272   grpc_metadata_array_destroy(&trailing_metadata_recv);
273   grpc_metadata_array_destroy(&request_metadata_recv);
274   grpc_call_details_destroy(&call_details);
275   grpc_byte_buffer_destroy(request_payload);
276   grpc_byte_buffer_destroy(recv_payload);
277 
278   grpc_call_unref(c);
279   if (s != nullptr) grpc_call_unref(s);
280 
281   cq_verifier_destroy(cqv);
282 
283   end_test(&f);
284   config.tear_down_data(&f);
285 }
286 
287 // Test with response larger than the limit.
288 // If send_limit is true, applies send limit on server; otherwise, applies
289 // recv limit on client.
test_max_message_length_on_response(grpc_end2end_test_config config,bool send_limit,bool use_service_config,bool use_string_json_value)290 static void test_max_message_length_on_response(grpc_end2end_test_config config,
291                                                 bool send_limit,
292                                                 bool use_service_config,
293                                                 bool use_string_json_value) {
294   gpr_log(GPR_INFO,
295           "testing response with send_limit=%d use_service_config=%d "
296           "use_string_json_value=%d",
297           send_limit, use_service_config, use_string_json_value);
298 
299   grpc_end2end_test_fixture f;
300   grpc_call* c = nullptr;
301   grpc_call* s = nullptr;
302   cq_verifier* cqv;
303   grpc_op ops[6];
304   grpc_op* op;
305   grpc_slice response_payload_slice =
306       grpc_slice_from_copied_string("hello world");
307   grpc_byte_buffer* response_payload =
308       grpc_raw_byte_buffer_create(&response_payload_slice, 1);
309   grpc_byte_buffer* recv_payload = nullptr;
310   grpc_metadata_array initial_metadata_recv;
311   grpc_metadata_array trailing_metadata_recv;
312   grpc_metadata_array request_metadata_recv;
313   grpc_call_details call_details;
314   grpc_status_code status;
315   grpc_call_error error;
316   grpc_slice details;
317   int was_cancelled = 2;
318 
319   grpc_channel_args* client_args = nullptr;
320   grpc_channel_args* server_args = nullptr;
321   if (use_service_config) {
322     // We don't currently support service configs on the server side.
323     GPR_ASSERT(!send_limit);
324     grpc_arg arg;
325     arg.type = GRPC_ARG_STRING;
326     arg.key = const_cast<char*>(GRPC_ARG_SERVICE_CONFIG);
327     arg.value.string = const_cast<char*>(
328         use_string_json_value
329             ? "{\n"
330               "  \"methodConfig\": [ {\n"
331               "    \"name\": [\n"
332               "      { \"service\": \"service\", \"method\": \"method\" }\n"
333               "    ],\n"
334               "    \"maxResponseMessageBytes\": \"5\"\n"
335               "  } ]\n"
336               "}"
337             : "{\n"
338               "  \"methodConfig\": [ {\n"
339               "    \"name\": [\n"
340               "      { \"service\": \"service\", \"method\": \"method\" }\n"
341               "    ],\n"
342               "    \"maxResponseMessageBytes\": 5\n"
343               "  } ]\n"
344               "}");
345     client_args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
346   } else {
347     // Set limit via channel args.
348     grpc_arg arg;
349     arg.key = send_limit
350                   ? const_cast<char*>(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH)
351                   : const_cast<char*>(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH);
352     arg.type = GRPC_ARG_INTEGER;
353     arg.value.integer = 5;
354     grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
355     if (send_limit) {
356       server_args = args;
357     } else {
358       client_args = args;
359     }
360   }
361 
362   f = begin_test(config, "test_max_response_message_length", client_args,
363                  server_args);
364   {
365     grpc_core::ExecCtx exec_ctx;
366     if (client_args != nullptr) grpc_channel_args_destroy(client_args);
367     if (server_args != nullptr) grpc_channel_args_destroy(server_args);
368   }
369   cqv = cq_verifier_create(f.cq);
370 
371   c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
372                                grpc_slice_from_static_string("/service/method"),
373                                nullptr, gpr_inf_future(GPR_CLOCK_REALTIME),
374                                nullptr);
375   GPR_ASSERT(c);
376 
377   grpc_metadata_array_init(&initial_metadata_recv);
378   grpc_metadata_array_init(&trailing_metadata_recv);
379   grpc_metadata_array_init(&request_metadata_recv);
380   grpc_call_details_init(&call_details);
381 
382   memset(ops, 0, sizeof(ops));
383   op = ops;
384   op->op = GRPC_OP_SEND_INITIAL_METADATA;
385   op->data.send_initial_metadata.count = 0;
386   op->flags = 0;
387   op->reserved = nullptr;
388   op++;
389   op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
390   op->flags = 0;
391   op->reserved = nullptr;
392   op++;
393   op->op = GRPC_OP_RECV_INITIAL_METADATA;
394   op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
395   op->flags = 0;
396   op->reserved = nullptr;
397   op++;
398   op->op = GRPC_OP_RECV_MESSAGE;
399   op->data.recv_message.recv_message = &recv_payload;
400   op->flags = 0;
401   op->reserved = nullptr;
402   op++;
403   op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
404   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
405   op->data.recv_status_on_client.status = &status;
406   op->data.recv_status_on_client.status_details = &details;
407   op->flags = 0;
408   op->reserved = nullptr;
409   op++;
410   error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
411                                 nullptr);
412   GPR_ASSERT(GRPC_CALL_OK == error);
413 
414   error =
415       grpc_server_request_call(f.server, &s, &call_details,
416                                &request_metadata_recv, f.cq, f.cq, tag(101));
417   GPR_ASSERT(GRPC_CALL_OK == error);
418   CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
419   cq_verify(cqv);
420 
421   memset(ops, 0, sizeof(ops));
422   op = ops;
423   op->op = GRPC_OP_SEND_INITIAL_METADATA;
424   op->data.send_initial_metadata.count = 0;
425   op->flags = 0;
426   op->reserved = nullptr;
427   op++;
428   op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
429   op->data.recv_close_on_server.cancelled = &was_cancelled;
430   op->flags = 0;
431   op->reserved = nullptr;
432   op++;
433   op->op = GRPC_OP_SEND_MESSAGE;
434   op->data.send_message.send_message = response_payload;
435   op->flags = 0;
436   op->reserved = nullptr;
437   op++;
438   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
439   op->data.send_status_from_server.trailing_metadata_count = 0;
440   op->data.send_status_from_server.status = GRPC_STATUS_OK;
441   grpc_slice status_details = grpc_slice_from_static_string("xyz");
442   op->data.send_status_from_server.status_details = &status_details;
443   op->flags = 0;
444   op->reserved = nullptr;
445   op++;
446   error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
447                                 nullptr);
448   GPR_ASSERT(GRPC_CALL_OK == error);
449 
450   CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
451   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
452   cq_verify(cqv);
453 
454   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
455   GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED);
456   GPR_ASSERT(
457       grpc_slice_str_cmp(
458           details, send_limit
459                        ? "Sent message larger than max (11 vs. 5)"
460                        : "Received message larger than max (11 vs. 5)") == 0);
461 
462   grpc_slice_unref(details);
463   grpc_metadata_array_destroy(&initial_metadata_recv);
464   grpc_metadata_array_destroy(&trailing_metadata_recv);
465   grpc_metadata_array_destroy(&request_metadata_recv);
466   grpc_call_details_destroy(&call_details);
467   grpc_byte_buffer_destroy(response_payload);
468   grpc_byte_buffer_destroy(recv_payload);
469 
470   grpc_call_unref(c);
471   if (s != nullptr) grpc_call_unref(s);
472 
473   cq_verifier_destroy(cqv);
474 
475   end_test(&f);
476   config.tear_down_data(&f);
477 }
478 
max_message_length(grpc_end2end_test_config config)479 void max_message_length(grpc_end2end_test_config config) {
480   test_max_message_length_on_request(config, false /* send_limit */,
481                                      false /* use_service_config */,
482                                      false /* use_string_json_value */);
483   test_max_message_length_on_request(config, true /* send_limit */,
484                                      false /* use_service_config */,
485                                      false /* use_string_json_value */);
486   test_max_message_length_on_response(config, false /* send_limit */,
487                                       false /* use_service_config */,
488                                       false /* use_string_json_value */);
489   test_max_message_length_on_response(config, true /* send_limit */,
490                                       false /* use_service_config */,
491                                       false /* use_string_json_value */);
492   test_max_message_length_on_request(config, true /* send_limit */,
493                                      true /* use_service_config */,
494                                      false /* use_string_json_value */);
495   test_max_message_length_on_request(config, true /* send_limit */,
496                                      true /* use_service_config */,
497                                      true /* use_string_json_value */);
498   test_max_message_length_on_response(config, false /* send_limit */,
499                                       true /* use_service_config */,
500                                       false /* use_string_json_value */);
501   test_max_message_length_on_response(config, false /* send_limit */,
502                                       true /* use_service_config */,
503                                       true /* use_string_json_value */);
504 }
505 
max_message_length_pre_init(void)506 void max_message_length_pre_init(void) {}
507