blob: fcdcaba6a23ddf6d7a4d0b25e251fef6c01bdfa0 [file] [log] [blame]
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001/*
2 *
3 * Copyright 2016, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
David Garcia Quintasd9cee6f2016-08-01 17:42:47 -070034#include <cinttypes>
David Garcia Quintasaaba1312016-06-22 18:10:37 -070035#include <cstdarg>
David Garcia Quintasd9cee6f2016-08-01 17:42:47 -070036#include <cstdint>
David Garcia Quintasaaba1312016-06-22 18:10:37 -070037#include <cstring>
38#include <string>
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070039
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -070040#include <gtest/gtest.h>
41
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070042#include <grpc/grpc.h>
David Garcia Quintas601bb122016-08-18 15:03:59 -070043#include <grpc/impl/codegen/byte_buffer_reader.h>
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070044#include <grpc/support/alloc.h>
45#include <grpc/support/host_port.h>
46#include <grpc/support/log.h>
47#include <grpc/support/string_util.h>
48#include <grpc/support/sync.h>
49#include <grpc/support/thd.h>
50#include <grpc/support/time.h>
51
David Garcia Quintas8a81aa12016-08-22 15:06:49 -070052#include <grpc++/impl/codegen/config.h>
David Garcia Quintas8a81aa12016-08-22 15:06:49 -070053extern "C" {
Mark D. Rotheb35a1d2016-10-19 14:53:42 -070054#include "src/core/ext/client_channel/client_channel.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070055#include "src/core/lib/channel/channel_stack.h"
David Garcia Quintas88006452016-08-24 06:53:23 -070056#include "src/core/lib/iomgr/sockaddr.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070057#include "src/core/lib/support/string.h"
58#include "src/core/lib/support/tmpfile.h"
59#include "src/core/lib/surface/channel.h"
60#include "src/core/lib/surface/server.h"
61#include "test/core/end2end/cq_verifier.h"
Mark D. Rothda0ec822016-10-03 11:32:04 -070062#include "test/core/end2end/fake_resolver.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070063#include "test/core/util/port.h"
64#include "test/core/util/test_config.h"
David Garcia Quintas55145c02016-06-21 14:51:54 -070065}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070066
David Garcia Quintasaaba1312016-06-22 18:10:37 -070067#include "src/proto/grpc/lb/v1/load_balancer.pb.h"
68
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070069#define NUM_BACKENDS 4
David Garcia Quintas5b0e9462016-08-15 19:38:39 -070070#define PAYLOAD "hello you"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070071
David Garcia Quintasf9f856b2016-06-22 18:25:53 -070072// TODO(dgq): Other scenarios in need of testing:
David Garcia Quintasea11d162016-07-14 17:27:28 -070073// - Send an empty serverlist update and verify that the client request blocks
74// until a new serverlist with actual contents is available.
David Garcia Quintasf9f856b2016-06-22 18:25:53 -070075// - Send identical serverlist update
David Garcia Quintas35c2aba2016-09-13 15:28:09 -070076// - Send a serverlist with faulty ip:port addresses (port > 2^16, etc).
David Garcia Quintasf9f856b2016-06-22 18:25:53 -070077// - Test reception of invalid serverlist
78// - Test pinging
David Garcia Quintas7ec29132016-11-01 04:09:05 +010079// - Test against a non-LB server.
David Garcia Quintasa26c77b2016-07-18 12:57:09 -070080// - Random LB server closing the stream unexpectedly.
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -070081// - Test using DNS-resolvable names (localhost?)
David Garcia Quintas149f09d2016-11-17 20:43:10 -080082// - Test handling of creation of faulty RR instance by having the LB return a
83// serverlist with non-existent backends after having initially returned a
84// valid one.
David Garcia Quintas7ec29132016-11-01 04:09:05 +010085//
86// Findings from end to end testing to be covered here:
87// - Handling of LB servers restart, including reconnection after backing-off
88// retries.
89// - Destruction of load balanced channel (and therefore of grpclb instance)
90// while:
91// 1) the internal LB call is still active. This should work by virtue
92// of the weak reference the LB call holds. The call should be terminated as
93// part of the grpclb shutdown process.
94// 2) the retry timer is active. Again, the weak reference it holds should
95// prevent a premature call to \a glb_destroy.
96// - Restart of backend servers with no changes to serverlist. This exercises
97// the RR handover mechanism.
David Garcia Quintasf9f856b2016-06-22 18:25:53 -070098
David Garcia Quintasaaba1312016-06-22 18:10:37 -070099namespace grpc {
100namespace {
101
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700102typedef struct client_fixture {
103 grpc_channel *client;
104 char *server_uri;
105 grpc_completion_queue *cq;
106} client_fixture;
107
108typedef struct server_fixture {
109 grpc_server *server;
110 grpc_call *server_call;
111 grpc_completion_queue *cq;
112 char *servers_hostport;
113 int port;
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800114 const char *lb_token_prefix;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700115 gpr_thd_id tid;
116 int num_calls_serviced;
117} server_fixture;
118
119typedef struct test_fixture {
120 server_fixture lb_server;
121 server_fixture lb_backends[NUM_BACKENDS];
122 client_fixture client;
123 int lb_server_update_delay_ms;
124} test_fixture;
125
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700126static void *tag(intptr_t t) { return (void *)t; }
127
Craig Tillerd41a4a72016-10-26 16:16:06 -0700128static grpc_slice build_response_payload_slice(
David Garcia Quintasaaba1312016-06-22 18:10:37 -0700129 const char *host, int *ports, size_t nports,
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800130 int64_t expiration_interval_secs, int32_t expiration_interval_nanos,
131 const char *token_prefix) {
David Garcia Quintasf9f856b2016-06-22 18:25:53 -0700132 // server_list {
133 // servers {
David Garcia Quintas8a81aa12016-08-22 15:06:49 -0700134 // ip_address: <in_addr/6 bytes of an IP>
135 // port: <16 bit uint>
David Garcia Quintasf9f856b2016-06-22 18:25:53 -0700136 // load_balance_token: "token..."
137 // }
138 // ...
139 // }
David Garcia Quintasaaba1312016-06-22 18:10:37 -0700140 grpc::lb::v1::LoadBalanceResponse response;
141 auto *serverlist = response.mutable_server_list();
142
143 if (expiration_interval_secs > 0 || expiration_interval_nanos > 0) {
144 auto *expiration_interval = serverlist->mutable_expiration_interval();
145 if (expiration_interval_secs > 0) {
146 expiration_interval->set_seconds(expiration_interval_secs);
147 }
148 if (expiration_interval_nanos > 0) {
149 expiration_interval->set_nanos(expiration_interval_nanos);
150 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700151 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700152 for (size_t i = 0; i < nports; i++) {
David Garcia Quintasaaba1312016-06-22 18:10:37 -0700153 auto *server = serverlist->add_servers();
David Garcia Quintas8a81aa12016-08-22 15:06:49 -0700154 // TODO(dgq): test ipv6
155 struct in_addr ip4;
156 GPR_ASSERT(inet_pton(AF_INET, host, &ip4) == 1);
157 server->set_ip_address(
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800158 string(reinterpret_cast<const char *>(&ip4), sizeof(ip4)));
David Garcia Quintasaaba1312016-06-22 18:10:37 -0700159 server->set_port(ports[i]);
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800160 // Missing tokens are acceptable. Test that path.
161 if (strlen(token_prefix) > 0) {
David Garcia Quintas0133a1b2016-11-15 15:42:37 -0800162 string token_data = token_prefix + std::to_string(ports[i]);
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800163 server->set_load_balance_token(token_data);
164 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700165 }
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800166 const string &enc_resp = response.SerializeAsString();
Craig Tillerd41a4a72016-10-26 16:16:06 -0700167 return grpc_slice_from_copied_buffer(enc_resp.data(), enc_resp.size());
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700168}
169
170static void drain_cq(grpc_completion_queue *cq) {
171 grpc_event ev;
172 do {
David Garcia Quintas4166cb02016-07-29 14:33:15 -0700173 ev = grpc_completion_queue_next(cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
174 NULL);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700175 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
176}
177
178static void sleep_ms(int delay_ms) {
179 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
180 gpr_time_from_millis(delay_ms, GPR_TIMESPAN)));
181}
182
183static void start_lb_server(server_fixture *sf, int *ports, size_t nports,
184 int update_delay_ms) {
185 grpc_call *s;
186 cq_verifier *cqv = cq_verifier_create(sf->cq);
187 grpc_op ops[6];
188 grpc_op *op;
189 grpc_metadata_array request_metadata_recv;
190 grpc_call_details call_details;
191 grpc_call_error error;
192 int was_cancelled = 2;
193 grpc_byte_buffer *request_payload_recv;
194 grpc_byte_buffer *response_payload;
195
196 memset(ops, 0, sizeof(ops));
197 grpc_metadata_array_init(&request_metadata_recv);
198 grpc_call_details_init(&call_details);
199
200 error = grpc_server_request_call(sf->server, &s, &call_details,
201 &request_metadata_recv, sf->cq, sf->cq,
202 tag(200));
203 GPR_ASSERT(GRPC_CALL_OK == error);
204 gpr_log(GPR_INFO, "LB Server[%s] up", sf->servers_hostport);
Mark D. Roth7f9bba82016-08-25 08:35:42 -0700205 CQ_EXPECT_COMPLETION(cqv, tag(200), 1);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700206 cq_verify(cqv);
207 gpr_log(GPR_INFO, "LB Server[%s] after tag 200", sf->servers_hostport);
208
David Garcia Quintas601bb122016-08-18 15:03:59 -0700209 // make sure we've received the initial metadata from the grpclb request.
210 GPR_ASSERT(request_metadata_recv.count > 0);
211 GPR_ASSERT(request_metadata_recv.metadata != NULL);
212
213 // receive request for backends
214 op = ops;
215 op->op = GRPC_OP_RECV_MESSAGE;
216 op->data.recv_message = &request_payload_recv;
217 op->flags = 0;
218 op->reserved = NULL;
219 op++;
220 error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(202), NULL);
221 GPR_ASSERT(GRPC_CALL_OK == error);
David Garcia Quintasb8245bd2016-09-01 18:29:46 +0200222 CQ_EXPECT_COMPLETION(cqv, tag(202), 1);
David Garcia Quintas601bb122016-08-18 15:03:59 -0700223 cq_verify(cqv);
224 gpr_log(GPR_INFO, "LB Server[%s] after RECV_MSG", sf->servers_hostport);
225
226 // validate initial request.
227 grpc_byte_buffer_reader bbr;
228 grpc_byte_buffer_reader_init(&bbr, request_payload_recv);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700229 grpc_slice request_payload_slice = grpc_byte_buffer_reader_readall(&bbr);
David Garcia Quintas601bb122016-08-18 15:03:59 -0700230 grpc::lb::v1::LoadBalanceRequest request;
Craig Tiller618e67d2016-10-26 21:08:10 -0700231 request.ParseFromArray(GRPC_SLICE_START_PTR(request_payload_slice),
232 GRPC_SLICE_LENGTH(request_payload_slice));
David Garcia Quintas601bb122016-08-18 15:03:59 -0700233 GPR_ASSERT(request.has_initial_request());
David Garcia Quintas55ba14a2016-09-27 18:45:30 -0700234 GPR_ASSERT(request.initial_request().name() == sf->servers_hostport);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700235 grpc_slice_unref(request_payload_slice);
David Garcia Quintas601bb122016-08-18 15:03:59 -0700236 grpc_byte_buffer_reader_destroy(&bbr);
237 grpc_byte_buffer_destroy(request_payload_recv);
238
Craig Tillerd41a4a72016-10-26 16:16:06 -0700239 grpc_slice response_payload_slice;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700240 op = ops;
241 op->op = GRPC_OP_SEND_INITIAL_METADATA;
242 op->data.send_initial_metadata.count = 0;
243 op->flags = 0;
244 op->reserved = NULL;
245 op++;
246 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
247 op->data.recv_close_on_server.cancelled = &was_cancelled;
248 op->flags = 0;
249 op->reserved = NULL;
250 op++;
251 error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(201), NULL);
252 GPR_ASSERT(GRPC_CALL_OK == error);
253 gpr_log(GPR_INFO, "LB Server[%s] after tag 201", sf->servers_hostport);
254
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700255 for (int i = 0; i < 2; i++) {
256 if (i == 0) {
257 // First half of the ports.
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800258 response_payload_slice = build_response_payload_slice(
259 "127.0.0.1", ports, nports / 2, -1, -1, sf->lb_token_prefix);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700260 } else {
261 // Second half of the ports.
262 sleep_ms(update_delay_ms);
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800263 response_payload_slice = build_response_payload_slice(
264 "127.0.0.1", ports + (nports / 2), (nports + 1) / 2 /* ceil */, -1,
265 -1, "" /* this half doesn't get to receive an LB token */);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700266 }
267
268 response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1);
269 op = ops;
270 op->op = GRPC_OP_SEND_MESSAGE;
271 op->data.send_message = response_payload;
272 op->flags = 0;
273 op->reserved = NULL;
274 op++;
275 error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(203), NULL);
276 GPR_ASSERT(GRPC_CALL_OK == error);
Mark D. Roth7f9bba82016-08-25 08:35:42 -0700277 CQ_EXPECT_COMPLETION(cqv, tag(203), 1);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700278 cq_verify(cqv);
279 gpr_log(GPR_INFO, "LB Server[%s] after SEND_MESSAGE, iter %d",
280 sf->servers_hostport, i);
281
282 grpc_byte_buffer_destroy(response_payload);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700283 grpc_slice_unref(response_payload_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700284 }
285 gpr_log(GPR_INFO, "LB Server[%s] shutting down", sf->servers_hostport);
286
287 op = ops;
288 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
289 op->data.send_status_from_server.trailing_metadata_count = 0;
290 op->data.send_status_from_server.status = GRPC_STATUS_OK;
291 op->data.send_status_from_server.status_details = "xyz";
292 op->flags = 0;
293 op->reserved = NULL;
294 op++;
295 error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(204), NULL);
296 GPR_ASSERT(GRPC_CALL_OK == error);
297
Mark D. Roth7f9bba82016-08-25 08:35:42 -0700298 CQ_EXPECT_COMPLETION(cqv, tag(201), 1);
299 CQ_EXPECT_COMPLETION(cqv, tag(204), 1);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700300 cq_verify(cqv);
301 gpr_log(GPR_INFO, "LB Server[%s] after tag 204. All done. LB server out",
302 sf->servers_hostport);
303
304 grpc_call_destroy(s);
305
306 cq_verifier_destroy(cqv);
307
308 grpc_metadata_array_destroy(&request_metadata_recv);
309 grpc_call_details_destroy(&call_details);
310}
311
312static void start_backend_server(server_fixture *sf) {
313 grpc_call *s;
314 cq_verifier *cqv;
315 grpc_op ops[6];
316 grpc_op *op;
317 grpc_metadata_array request_metadata_recv;
318 grpc_call_details call_details;
319 grpc_call_error error;
320 int was_cancelled;
321 grpc_byte_buffer *request_payload_recv;
322 grpc_byte_buffer *response_payload;
323 grpc_event ev;
324
325 while (true) {
326 memset(ops, 0, sizeof(ops));
327 cqv = cq_verifier_create(sf->cq);
328 was_cancelled = 2;
329 grpc_metadata_array_init(&request_metadata_recv);
330 grpc_call_details_init(&call_details);
331
332 error = grpc_server_request_call(sf->server, &s, &call_details,
333 &request_metadata_recv, sf->cq, sf->cq,
334 tag(100));
335 GPR_ASSERT(GRPC_CALL_OK == error);
336 gpr_log(GPR_INFO, "Server[%s] up", sf->servers_hostport);
David Garcia Quintas4166cb02016-07-29 14:33:15 -0700337 ev = grpc_completion_queue_next(sf->cq,
338 GRPC_TIMEOUT_SECONDS_TO_DEADLINE(60), NULL);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700339 if (!ev.success) {
340 gpr_log(GPR_INFO, "Server[%s] being torn down", sf->servers_hostport);
341 cq_verifier_destroy(cqv);
342 grpc_metadata_array_destroy(&request_metadata_recv);
343 grpc_call_details_destroy(&call_details);
344 return;
345 }
346 GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800347 const string expected_token =
David Garcia Quintas1a2e40e2016-11-18 13:05:53 -0800348 strlen(sf->lb_token_prefix) == 0 ? "" : sf->lb_token_prefix +
349 std::to_string(sf->port);
David Garcia Quintasa3654db2016-10-11 15:52:39 -0700350 GPR_ASSERT(contains_metadata(&request_metadata_recv, "lb-token",
David Garcia Quintas8a81aa12016-08-22 15:06:49 -0700351 expected_token.c_str()));
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700352
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700353 gpr_log(GPR_INFO, "Server[%s] after tag 100", sf->servers_hostport);
354
355 op = ops;
356 op->op = GRPC_OP_SEND_INITIAL_METADATA;
357 op->data.send_initial_metadata.count = 0;
358 op->flags = 0;
359 op->reserved = NULL;
360 op++;
361 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
362 op->data.recv_close_on_server.cancelled = &was_cancelled;
363 op->flags = 0;
364 op->reserved = NULL;
365 op++;
366 error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(101), NULL);
367 GPR_ASSERT(GRPC_CALL_OK == error);
368 gpr_log(GPR_INFO, "Server[%s] after tag 101", sf->servers_hostport);
369
370 bool exit = false;
Craig Tillerd41a4a72016-10-26 16:16:06 -0700371 grpc_slice response_payload_slice = grpc_slice_from_copied_string(PAYLOAD);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700372 while (!exit) {
373 op = ops;
374 op->op = GRPC_OP_RECV_MESSAGE;
375 op->data.recv_message = &request_payload_recv;
376 op->flags = 0;
377 op->reserved = NULL;
378 op++;
379 error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
380 GPR_ASSERT(GRPC_CALL_OK == error);
David Garcia Quintas4166cb02016-07-29 14:33:15 -0700381 ev = grpc_completion_queue_next(
382 sf->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), NULL);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700383 if (ev.type == GRPC_OP_COMPLETE && ev.success) {
384 GPR_ASSERT(ev.tag = tag(102));
385 if (request_payload_recv == NULL) {
386 exit = true;
387 gpr_log(GPR_INFO,
388 "Server[%s] recv \"close\" from client, exiting. Call #%d",
389 sf->servers_hostport, sf->num_calls_serviced);
390 }
391 } else {
392 gpr_log(GPR_INFO, "Server[%s] forced to shutdown. Call #%d",
393 sf->servers_hostport, sf->num_calls_serviced);
394 exit = true;
395 }
396 gpr_log(GPR_INFO, "Server[%s] after tag 102. Call #%d",
397 sf->servers_hostport, sf->num_calls_serviced);
398
399 if (!exit) {
400 response_payload =
401 grpc_raw_byte_buffer_create(&response_payload_slice, 1);
402 op = ops;
403 op->op = GRPC_OP_SEND_MESSAGE;
404 op->data.send_message = response_payload;
405 op->flags = 0;
406 op->reserved = NULL;
407 op++;
408 error =
409 grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL);
410 GPR_ASSERT(GRPC_CALL_OK == error);
David Garcia Quintas4166cb02016-07-29 14:33:15 -0700411 ev = grpc_completion_queue_next(
412 sf->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), NULL);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700413 if (ev.type == GRPC_OP_COMPLETE && ev.success) {
414 GPR_ASSERT(ev.tag = tag(103));
415 } else {
416 gpr_log(GPR_INFO, "Server[%s] forced to shutdown. Call #%d",
417 sf->servers_hostport, sf->num_calls_serviced);
418 exit = true;
419 }
420 gpr_log(GPR_INFO, "Server[%s] after tag 103. Call #%d",
421 sf->servers_hostport, sf->num_calls_serviced);
422 grpc_byte_buffer_destroy(response_payload);
423 }
424
425 grpc_byte_buffer_destroy(request_payload_recv);
426 }
427 ++sf->num_calls_serviced;
428
429 gpr_log(GPR_INFO, "Server[%s] OUT OF THE LOOP", sf->servers_hostport);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700430 grpc_slice_unref(response_payload_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700431
432 op = ops;
433 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
434 op->data.send_status_from_server.trailing_metadata_count = 0;
435 op->data.send_status_from_server.status = GRPC_STATUS_OK;
436 op->data.send_status_from_server.status_details = "Backend server out a-ok";
437 op->flags = 0;
438 op->reserved = NULL;
439 op++;
440 error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL);
441 GPR_ASSERT(GRPC_CALL_OK == error);
442
Mark D. Roth7f9bba82016-08-25 08:35:42 -0700443 CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
444 CQ_EXPECT_COMPLETION(cqv, tag(104), 1);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700445 cq_verify(cqv);
446 gpr_log(GPR_INFO, "Server[%s] DONE. After servicing %d calls",
David Garcia Quintas8782d1b2016-06-15 23:58:44 -0700447 sf->servers_hostport, sf->num_calls_serviced);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700448
449 grpc_call_destroy(s);
450 cq_verifier_destroy(cqv);
451 grpc_metadata_array_destroy(&request_metadata_recv);
452 grpc_call_details_destroy(&call_details);
453 }
454}
455
456static void perform_request(client_fixture *cf) {
457 grpc_call *c;
458 cq_verifier *cqv = cq_verifier_create(cf->cq);
459 grpc_op ops[6];
460 grpc_op *op;
461 grpc_metadata_array initial_metadata_recv;
462 grpc_metadata_array trailing_metadata_recv;
463 grpc_status_code status;
464 grpc_call_error error;
465 char *details = NULL;
466 size_t details_capacity = 0;
467 grpc_byte_buffer *request_payload;
468 grpc_byte_buffer *response_payload_recv;
469 int i;
470
471 memset(ops, 0, sizeof(ops));
Craig Tiller28b72422016-10-26 21:15:29 -0700472 grpc_slice request_payload_slice =
473 grpc_slice_from_copied_string("hello world");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700474
475 c = grpc_channel_create_call(cf->client, NULL, GRPC_PROPAGATE_DEFAULTS,
476 cf->cq, "/foo", "foo.test.google.fr:1234",
David Garcia Quintasbd57bba2016-09-30 14:44:56 -0700477 GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700478 gpr_log(GPR_INFO, "Call 0x%" PRIxPTR " created", (intptr_t)c);
479 GPR_ASSERT(c);
480 char *peer;
481
482 grpc_metadata_array_init(&initial_metadata_recv);
483 grpc_metadata_array_init(&trailing_metadata_recv);
484
485 op = ops;
486 op->op = GRPC_OP_SEND_INITIAL_METADATA;
487 op->data.send_initial_metadata.count = 0;
488 op->flags = 0;
489 op->reserved = NULL;
490 op++;
491 op->op = GRPC_OP_RECV_INITIAL_METADATA;
492 op->data.recv_initial_metadata = &initial_metadata_recv;
493 op->flags = 0;
494 op->reserved = NULL;
495 op++;
496 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
497 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
498 op->data.recv_status_on_client.status = &status;
499 op->data.recv_status_on_client.status_details = &details;
500 op->data.recv_status_on_client.status_details_capacity = &details_capacity;
501 op->flags = 0;
502 op->reserved = NULL;
503 op++;
504 error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
505 GPR_ASSERT(GRPC_CALL_OK == error);
506
507 for (i = 0; i < 4; i++) {
508 request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
509
510 op = ops;
511 op->op = GRPC_OP_SEND_MESSAGE;
512 op->data.send_message = request_payload;
513 op->flags = 0;
514 op->reserved = NULL;
515 op++;
516 op->op = GRPC_OP_RECV_MESSAGE;
517 op->data.recv_message = &response_payload_recv;
518 op->flags = 0;
519 op->reserved = NULL;
520 op++;
521 error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL);
522 GPR_ASSERT(GRPC_CALL_OK == error);
523
Mark D. Roth7f9bba82016-08-25 08:35:42 -0700524 CQ_EXPECT_COMPLETION(cqv, tag(2), 1);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700525 cq_verify(cqv);
David Garcia Quintas033c51e2016-11-30 00:49:29 -0800526 gpr_log(GPR_INFO, "Client after sending msg %d / 4", i + 1);
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700527 GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, PAYLOAD));
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700528
529 grpc_byte_buffer_destroy(request_payload);
530 grpc_byte_buffer_destroy(response_payload_recv);
531 }
532
Craig Tillerd41a4a72016-10-26 16:16:06 -0700533 grpc_slice_unref(request_payload_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700534
535 op = ops;
536 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
537 op->flags = 0;
538 op->reserved = NULL;
539 op++;
540 error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL);
541 GPR_ASSERT(GRPC_CALL_OK == error);
542
Mark D. Roth7f9bba82016-08-25 08:35:42 -0700543 CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
544 CQ_EXPECT_COMPLETION(cqv, tag(3), 1);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700545 cq_verify(cqv);
546 peer = grpc_call_get_peer(c);
547 gpr_log(GPR_INFO, "Client DONE WITH SERVER %s ", peer);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700548
549 grpc_call_destroy(c);
550
David Garcia Quintas033c51e2016-11-30 00:49:29 -0800551 cq_verify_empty_timeout(cqv, 1 /* seconds */);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700552 cq_verifier_destroy(cqv);
553
554 grpc_metadata_array_destroy(&initial_metadata_recv);
555 grpc_metadata_array_destroy(&trailing_metadata_recv);
556 gpr_free(details);
David Garcia Quintas033c51e2016-11-30 00:49:29 -0800557 gpr_log(GPR_INFO, "Client call (peer %s) DESTROYED.", peer);
558 gpr_free(peer);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700559}
560
561static void setup_client(const char *server_hostport, client_fixture *cf) {
562 cf->cq = grpc_completion_queue_create(NULL);
563 cf->server_uri = gpr_strdup(server_hostport);
564 cf->client = grpc_insecure_channel_create(cf->server_uri, NULL, NULL);
565}
566
567static void teardown_client(client_fixture *cf) {
568 grpc_completion_queue_shutdown(cf->cq);
569 drain_cq(cf->cq);
570 grpc_completion_queue_destroy(cf->cq);
571 cf->cq = NULL;
572 grpc_channel_destroy(cf->client);
573 cf->client = NULL;
574 gpr_free(cf->server_uri);
575}
576
577static void setup_server(const char *host, server_fixture *sf) {
578 int assigned_port;
579
580 sf->cq = grpc_completion_queue_create(NULL);
David Garcia Quintas55145c02016-06-21 14:51:54 -0700581 const char *colon_idx = strchr(host, ':');
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700582 if (colon_idx) {
David Garcia Quintas55145c02016-06-21 14:51:54 -0700583 const char *port_str = colon_idx + 1;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700584 sf->port = atoi(port_str);
585 sf->servers_hostport = gpr_strdup(host);
586 } else {
587 sf->port = grpc_pick_unused_port_or_die();
588 gpr_join_host_port(&sf->servers_hostport, host, sf->port);
589 }
590
591 sf->server = grpc_server_create(NULL, NULL);
592 grpc_server_register_completion_queue(sf->server, sf->cq, NULL);
593 GPR_ASSERT((assigned_port = grpc_server_add_insecure_http2_port(
594 sf->server, sf->servers_hostport)) > 0);
595 GPR_ASSERT(sf->port == assigned_port);
596 grpc_server_start(sf->server);
597}
598
599static void teardown_server(server_fixture *sf) {
600 if (!sf->server) return;
601
602 gpr_log(GPR_INFO, "Server[%s] shutting down", sf->servers_hostport);
603 grpc_server_shutdown_and_notify(sf->server, sf->cq, tag(1000));
604 GPR_ASSERT(grpc_completion_queue_pluck(
605 sf->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
606 .type == GRPC_OP_COMPLETE);
607 grpc_server_destroy(sf->server);
608 gpr_thd_join(sf->tid);
609
610 sf->server = NULL;
611 grpc_completion_queue_shutdown(sf->cq);
612 drain_cq(sf->cq);
613 grpc_completion_queue_destroy(sf->cq);
614
615 gpr_log(GPR_INFO, "Server[%s] bye bye", sf->servers_hostport);
616 gpr_free(sf->servers_hostport);
617}
618
619static void fork_backend_server(void *arg) {
David Garcia Quintas55145c02016-06-21 14:51:54 -0700620 server_fixture *sf = static_cast<server_fixture *>(arg);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700621 start_backend_server(sf);
622}
623
624static void fork_lb_server(void *arg) {
David Garcia Quintas55145c02016-06-21 14:51:54 -0700625 test_fixture *tf = static_cast<test_fixture *>(arg);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700626 int ports[NUM_BACKENDS];
627 for (int i = 0; i < NUM_BACKENDS; i++) {
628 ports[i] = tf->lb_backends[i].port;
629 }
630 start_lb_server(&tf->lb_server, ports, NUM_BACKENDS,
631 tf->lb_server_update_delay_ms);
632}
633
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800634#define LB_TOKEN_PREFIX "token"
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700635static test_fixture setup_test_fixture(int lb_server_update_delay_ms) {
636 test_fixture tf;
637 memset(&tf, 0, sizeof(tf));
638 tf.lb_server_update_delay_ms = lb_server_update_delay_ms;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700639
640 gpr_thd_options options = gpr_thd_options_default();
641 gpr_thd_options_set_joinable(&options);
642
643 for (int i = 0; i < NUM_BACKENDS; ++i) {
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800644 // Only the first half of the servers expect an LB token.
645 if (i < NUM_BACKENDS / 2) {
646 tf.lb_backends[i].lb_token_prefix = LB_TOKEN_PREFIX;
647 } else {
648 tf.lb_backends[i].lb_token_prefix = "";
649 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700650 setup_server("127.0.0.1", &tf.lb_backends[i]);
651 gpr_thd_new(&tf.lb_backends[i].tid, fork_backend_server, &tf.lb_backends[i],
652 &options);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700653 }
654
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800655 tf.lb_server.lb_token_prefix = LB_TOKEN_PREFIX;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700656 setup_server("127.0.0.1", &tf.lb_server);
657 gpr_thd_new(&tf.lb_server.tid, fork_lb_server, &tf.lb_server, &options);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700658
659 char *server_uri;
Mark D. Rothe127a392016-10-27 08:27:15 -0700660 // The grpclb LB policy will be automatically selected by virtue of
661 // the fact that the returned addresses are balancer addresses.
662 gpr_asprintf(&server_uri, "test:%s?lb_enabled=1",
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700663 tf.lb_server.servers_hostport);
664 setup_client(server_uri, &tf.client);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700665 gpr_free(server_uri);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700666
667 return tf;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700668}
669
670static void teardown_test_fixture(test_fixture *tf) {
671 teardown_client(&tf->client);
672 for (int i = 0; i < NUM_BACKENDS; ++i) {
673 teardown_server(&tf->lb_backends[i]);
674 }
675 teardown_server(&tf->lb_server);
676}
677
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700678// The LB server will send two updates: batch 1 and batch 2. Each batch contains
679// two addresses, both of a valid and running backend server. Batch 1 is readily
680// available and provided as soon as the client establishes the streaming call.
681// Batch 2 is sent after a delay of \a lb_server_update_delay_ms milliseconds.
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700682static test_fixture test_update(int lb_server_update_delay_ms) {
David Garcia Quintasaaba1312016-06-22 18:10:37 -0700683 gpr_log(GPR_INFO, "start %s(%d)", __func__, lb_server_update_delay_ms);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700684 test_fixture tf = setup_test_fixture(lb_server_update_delay_ms);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700685 perform_request(
686 &tf.client); // "consumes" 1st backend server of 1st serverlist
687 perform_request(
688 &tf.client); // "consumes" 2nd backend server of 1st serverlist
689
690 perform_request(
691 &tf.client); // "consumes" 1st backend server of 2nd serverlist
692 perform_request(
693 &tf.client); // "consumes" 2nd backend server of 2nd serverlist
694
695 teardown_test_fixture(&tf);
David Garcia Quintasaaba1312016-06-22 18:10:37 -0700696 gpr_log(GPR_INFO, "end %s(%d)", __func__, lb_server_update_delay_ms);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700697 return tf;
698}
699
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700700TEST(GrpclbTest, Updates) {
David Garcia Quintasaaba1312016-06-22 18:10:37 -0700701 grpc::test_fixture tf_result;
David Garcia Quintas033c51e2016-11-30 00:49:29 -0800702 // Clients take at least one second to complete a call (the last part of the
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700703 // call sleeps for 1 second while verifying the client's completion queue is
David Garcia Quintas033c51e2016-11-30 00:49:29 -0800704 // empty), more if the system is under load. Therefore:
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700705 //
706 // If the LB server waits 800ms before sending an update, it will arrive
David Garcia Quintas033c51e2016-11-30 00:49:29 -0800707 // before the first client request finishes, skipping the second server from
708 // batch 1. All subsequent picks will come from the second half of the
709 // backends, those coming in the LB update.
David Garcia Quintasaaba1312016-06-22 18:10:37 -0700710 tf_result = grpc::test_update(800);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700711 GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 1);
712 GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 0);
David Garcia Quintas033c51e2016-11-30 00:49:29 -0800713 GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced +
714 tf_result.lb_backends[3].num_calls_serviced >
715 0);
716 int num_serviced_calls = 0;
717 for (int i = 0; i < 4; i++) {
718 num_serviced_calls += tf_result.lb_backends[i].num_calls_serviced;
719 }
720 GPR_ASSERT(num_serviced_calls == 4);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700721
David Garcia Quintas033c51e2016-11-30 00:49:29 -0800722 // If the LB server waits 2500ms, the update arrives after two calls and three
723 // picks. The third pick will be the 1st server of the 1st update (RR policy
724 // going around). The fourth and final pick will come from the second LB
725 // update. In any case, the total number of serviced calls must again be equal
726 // to four across all the backends.
David Garcia Quintase60ae9c2016-08-02 16:37:41 -0700727 tf_result = grpc::test_update(2500);
728 GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced >= 1);
David Garcia Quintas033c51e2016-11-30 00:49:29 -0800729 GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 1);
730 GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced +
731 tf_result.lb_backends[3].num_calls_serviced >
732 0);
733 num_serviced_calls = 0;
734 for (int i = 0; i < 4; i++) {
735 num_serviced_calls += tf_result.lb_backends[i].num_calls_serviced;
736 }
737 GPR_ASSERT(num_serviced_calls == 4);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700738}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700739
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700740TEST(GrpclbTest, InvalidAddressInServerlist) {}
741
742} // namespace
743} // namespace grpc
744
745int main(int argc, char **argv) {
746 ::testing::InitGoogleTest(&argc, argv);
747 grpc_test_init(argc, argv);
Mark D. Rothda0ec822016-10-03 11:32:04 -0700748 grpc_fake_resolver_init();
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700749 grpc_init();
750 const auto result = RUN_ALL_TESTS();
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700751 grpc_shutdown();
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700752 return result;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700753}