blob: 4e7c59569c27b3dd74ffa8fabe6efaab5969c95f [file] [log] [blame]
David Garcia Quintas4fb049b2015-09-03 17:26:06 -07001/*
2 *
3 * Copyright 2015, 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 Quintasfe7a6362015-09-10 11:06:46 -070034#include <stdarg.h>
David Garcia Quintas4fb049b2015-09-03 17:26:06 -070035#include <string.h>
36
37#include <grpc/grpc.h>
38#include <grpc/support/alloc.h>
39#include <grpc/support/host_port.h>
40#include <grpc/support/log.h>
David Garcia Quintasfe7a6362015-09-10 11:06:46 -070041#include <grpc/support/time.h>
David Garcia Quintas4fb049b2015-09-03 17:26:06 -070042#include <grpc/support/string_util.h>
43
44#include "src/core/channel/channel_stack.h"
45#include "src/core/surface/channel.h"
46#include "src/core/channel/client_channel.h"
David Garcia Quintas4fb049b2015-09-03 17:26:06 -070047#include "src/core/support/string.h"
David Garcia Quintasfe7a6362015-09-10 11:06:46 -070048#include "src/core/surface/server.h"
David Garcia Quintas4fb049b2015-09-03 17:26:06 -070049#include "test/core/util/test_config.h"
50#include "test/core/util/port.h"
51#include "test/core/end2end/cq_verifier.h"
52
53typedef struct servers_fixture {
54 size_t num_servers;
55 grpc_server **servers;
56 grpc_call **server_calls;
57 grpc_completion_queue *cq;
58 char **servers_hostports;
59 grpc_metadata_array *request_metadata_recv;
60} servers_fixture;
61
62typedef void (*verifier_fn)(const servers_fixture *, grpc_channel *,
63 const int *, const size_t);
64
65typedef struct test_spec {
66 size_t num_iters;
67 size_t num_servers;
68
69 int **kill_at;
70 int **revive_at;
71
David Garcia Quintasfe7a6362015-09-10 11:06:46 -070072 const char *description;
73
David Garcia Quintas4fb049b2015-09-03 17:26:06 -070074 verifier_fn verifier;
75
76} test_spec;
77
78static void test_spec_reset(test_spec *spec) {
79 size_t i, j;
80
81 for (i = 0; i < spec->num_iters; i++) {
82 for (j = 0; j < spec->num_servers; j++) {
83 spec->kill_at[i][j] = 0;
84 spec->revive_at[i][j] = 0;
85 }
86 }
87}
88
David Garcia Quintasa4c43a62015-09-11 13:33:57 -070089static test_spec *test_spec_create(size_t num_iters, size_t num_servers) {
David Garcia Quintas4fb049b2015-09-03 17:26:06 -070090 test_spec *spec;
91 size_t i;
92
93 spec = gpr_malloc(sizeof(test_spec));
94 spec->num_iters = num_iters;
95 spec->num_servers = num_servers;
David Garcia Quintasa4c43a62015-09-11 13:33:57 -070096 spec->kill_at = gpr_malloc(sizeof(int *) * num_iters);
97 spec->revive_at = gpr_malloc(sizeof(int *) * num_iters);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -070098 for (i = 0; i < num_iters; i++) {
99 spec->kill_at[i] = gpr_malloc(sizeof(int) * num_servers);
100 spec->revive_at[i] = gpr_malloc(sizeof(int) * num_servers);
101 }
102
103 test_spec_reset(spec);
104 return spec;
105}
106
107static void test_spec_destroy(test_spec *spec) {
108 size_t i;
109 for (i = 0; i < spec->num_iters; i++) {
110 gpr_free(spec->kill_at[i]);
111 gpr_free(spec->revive_at[i]);
112 }
113
114 gpr_free(spec->kill_at);
115 gpr_free(spec->revive_at);
116
117 gpr_free(spec);
118}
119
120static void *tag(gpr_intptr t) { return (void *)t; }
121
122static gpr_timespec n_seconds_time(int n) {
123 return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
124}
125
126static void drain_cq(grpc_completion_queue *cq) {
127 grpc_event ev;
128 do {
129 ev = grpc_completion_queue_next(cq, n_seconds_time(5), NULL);
130 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
131}
132
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700133static void kill_server(const servers_fixture *f, size_t i) {
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700134 gpr_log(GPR_INFO, "KILLING SERVER %d", i);
135 GPR_ASSERT(f->servers[i] != NULL);
136 grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700137 GPR_ASSERT(grpc_completion_queue_pluck(
138 f->cq, tag(10000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700139 .type == GRPC_OP_COMPLETE);
140 grpc_server_destroy(f->servers[i]);
141 f->servers[i] = NULL;
142}
143
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700144static void revive_server(const servers_fixture *f, size_t i) {
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700145 int got_port;
146 gpr_log(GPR_INFO, "RAISE AGAIN SERVER %d", i);
147 GPR_ASSERT(f->servers[i] == NULL);
148 f->servers[i] = grpc_server_create(NULL, NULL);
149 grpc_server_register_completion_queue(f->servers[i], f->cq, NULL);
150 GPR_ASSERT((got_port = grpc_server_add_insecure_http2_port(
151 f->servers[i], f->servers_hostports[i])) > 0);
152 grpc_server_start(f->servers[i]);
153}
154
155static servers_fixture *setup_servers(const char *server_host,
156 const size_t num_servers) {
157 servers_fixture *f = gpr_malloc(sizeof(servers_fixture));
158 int *ports;
159 int got_port;
160 size_t i;
161
162 f->num_servers = num_servers;
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700163 f->server_calls = gpr_malloc(sizeof(grpc_call *) * num_servers);
164 f->request_metadata_recv =
165 gpr_malloc(sizeof(grpc_metadata_array) * num_servers);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700166 /* Create servers. */
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700167 ports = gpr_malloc(sizeof(int *) * num_servers);
168 f->servers = gpr_malloc(sizeof(grpc_server *) * num_servers);
169 f->servers_hostports = gpr_malloc(sizeof(char *) * num_servers);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700170 f->cq = grpc_completion_queue_create(NULL);
171 for (i = 0; i < num_servers; i++) {
172 ports[i] = grpc_pick_unused_port_or_die();
173
174 gpr_join_host_port(&f->servers_hostports[i], server_host, ports[i]);
175
176 f->servers[i] = grpc_server_create(NULL, NULL);
177 grpc_server_register_completion_queue(f->servers[i], f->cq, NULL);
178 GPR_ASSERT((got_port = grpc_server_add_insecure_http2_port(
179 f->servers[i], f->servers_hostports[i])) > 0);
180 GPR_ASSERT(ports[i] == got_port);
181 grpc_server_start(f->servers[i]);
182 }
183 gpr_free(ports);
184 return f;
185}
186
187static void teardown_servers(servers_fixture *f) {
188 size_t i;
189 /* Destroy server. */
190 for (i = 0; i < f->num_servers; i++) {
191 if (f->servers[i] == NULL) continue;
192 grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700193 GPR_ASSERT(grpc_completion_queue_pluck(
194 f->cq, tag(10000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700195 .type == GRPC_OP_COMPLETE);
196 grpc_server_destroy(f->servers[i]);
197 }
198 grpc_completion_queue_shutdown(f->cq);
199 drain_cq(f->cq);
200 grpc_completion_queue_destroy(f->cq);
201
202 gpr_free(f->servers);
203
204 for (i = 0; i < f->num_servers; i++) {
205 gpr_free(f->servers_hostports[i]);
206 }
207
208 gpr_free(f->servers_hostports);
209 gpr_free(f->request_metadata_recv);
210 gpr_free(f->server_calls);
211 gpr_free(f);
212}
213
214/** Returns connection sequence (server indices), which must be freed */
215int *perform_request(servers_fixture *f, grpc_channel *client,
216 const test_spec *spec) {
217 grpc_call *c;
218 int s_idx;
219 int *s_valid;
220 gpr_timespec deadline;
221 grpc_op ops[6];
222 grpc_op *op;
223 grpc_status_code status;
224 char *details;
225 size_t details_capacity;
226 int was_cancelled;
227 grpc_call_details *call_details;
228 size_t i, iter_num;
229 grpc_event ev;
230 int read_tag;
231 int *connection_sequence;
232 grpc_metadata_array initial_metadata_recv;
233 grpc_metadata_array trailing_metadata_recv;
234
235 s_valid = gpr_malloc(sizeof(int) * f->num_servers);
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700236 call_details = gpr_malloc(sizeof(grpc_call_details) * f->num_servers);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700237 connection_sequence = gpr_malloc(sizeof(int) * spec->num_iters);
238
239 /* Send a trivial request. */
240 deadline = n_seconds_time(60);
241
242 for (iter_num = 0; iter_num < spec->num_iters; iter_num++) {
243 cq_verifier *cqv = cq_verifier_create(f->cq);
244 details = NULL;
245 details_capacity = 0;
246 was_cancelled = 2;
247
248 for (i = 0; i < f->num_servers; i++) {
249 if (spec->kill_at[iter_num][i] != 0) {
250 kill_server(f, i);
251 } else if (spec->revive_at[iter_num][i] != 0) {
252 /* killing takes precedence */
253 revive_server(f, i);
254 }
255 }
256
257 connection_sequence[iter_num] = -1;
258 grpc_metadata_array_init(&initial_metadata_recv);
259 grpc_metadata_array_init(&trailing_metadata_recv);
260
261 for (i = 0; i < f->num_servers; i++) {
262 grpc_call_details_init(&call_details[i]);
263 }
264 memset(s_valid, 0, f->num_servers * sizeof(int));
265
266 c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
267 "/foo", "foo.test.google.fr", deadline, NULL);
268 GPR_ASSERT(c);
269
270 op = ops;
271 op->op = GRPC_OP_SEND_INITIAL_METADATA;
272 op->data.send_initial_metadata.count = 0;
273 op->flags = 0;
274 op->reserved = NULL;
275 op++;
276 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
277 op->flags = 0;
278 op->reserved = NULL;
279 op++;
280 op->op = GRPC_OP_RECV_INITIAL_METADATA;
281 op->data.recv_initial_metadata = &initial_metadata_recv;
282 op->flags = 0;
283 op->reserved = NULL;
284 op++;
285 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
286 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
287 op->data.recv_status_on_client.status = &status;
288 op->data.recv_status_on_client.status_details = &details;
289 op->data.recv_status_on_client.status_details_capacity = &details_capacity;
290 op->flags = 0;
291 op->reserved = NULL;
292 op++;
293 GPR_ASSERT(GRPC_CALL_OK ==
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700294 grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL));
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700295
296 /* "listen" on all servers */
297 for (i = 0; i < f->num_servers; i++) {
298 grpc_metadata_array_init(&f->request_metadata_recv[i]);
299 if (f->servers[i] != NULL) {
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700300 GPR_ASSERT(GRPC_CALL_OK ==
301 grpc_server_request_call(f->servers[i], &f->server_calls[i],
302 &call_details[i],
303 &f->request_metadata_recv[i], f->cq,
304 f->cq, tag(1000 + (int)i)));
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700305 }
306 }
307
308 s_idx = -1;
309 while ((ev = grpc_completion_queue_next(
310 f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL))
311 .type != GRPC_QUEUE_TIMEOUT) {
312 read_tag = ((int)(gpr_intptr)ev.tag);
313 gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%d",
314 ev.success, ev.type, read_tag, iter_num);
315 if (ev.success && read_tag >= 1000) {
316 GPR_ASSERT(s_idx == -1); /* only one server must reply */
317 /* only server notifications for non-shutdown events */
318 s_idx = read_tag - 1000;
319 s_valid[s_idx] = 1;
320 connection_sequence[iter_num] = s_idx;
321 }
322 }
323
324 if (s_idx >= 0) {
325 op = ops;
326 op->op = GRPC_OP_SEND_INITIAL_METADATA;
327 op->data.send_initial_metadata.count = 0;
328 op->flags = 0;
329 op->reserved = NULL;
330 op++;
331 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
332 op->data.send_status_from_server.trailing_metadata_count = 0;
333 op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
334 op->data.send_status_from_server.status_details = "xyz";
335 op->flags = 0;
336 op->reserved = NULL;
337 op++;
338 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
339 op->data.recv_close_on_server.cancelled = &was_cancelled;
340 op->flags = 0;
341 op->reserved = NULL;
342 op++;
343 GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(f->server_calls[s_idx],
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700344 ops, (size_t)(op - ops),
345 tag(102), NULL));
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700346
347 cq_expect_completion(cqv, tag(102), 1);
348 cq_expect_completion(cqv, tag(1), 1);
349 cq_verify(cqv);
350
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700351 GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
352 GPR_ASSERT(0 == strcmp(details, "xyz"));
353 GPR_ASSERT(0 == strcmp(call_details[s_idx].method, "/foo"));
354 GPR_ASSERT(0 == strcmp(call_details[s_idx].host, "foo.test.google.fr"));
355 GPR_ASSERT(was_cancelled == 1);
356 }
357
358 for (i = 0; i < f->num_servers; i++) {
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700359 if (s_valid[i] != 0) {
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700360 grpc_call_destroy(f->server_calls[i]);
361 }
362 grpc_metadata_array_destroy(&f->request_metadata_recv[i]);
363 }
364 grpc_metadata_array_destroy(&initial_metadata_recv);
365 grpc_metadata_array_destroy(&trailing_metadata_recv);
366
367 cq_verifier_destroy(cqv);
368
369 grpc_call_destroy(c);
370
371 for (i = 0; i < f->num_servers; i++) {
372 grpc_call_details_destroy(&call_details[i]);
373 }
374 gpr_free(details);
375 }
376
377 gpr_free(call_details);
378 gpr_free(s_valid);
379
380 return connection_sequence;
381}
382
383static void assert_channel_connectivity(
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700384 grpc_channel *ch, size_t num_accepted_conn_states,
David Garcia Quintas56d66c22015-09-11 22:19:18 -0700385 grpc_connectivity_state accepted_conn_state, ...) {
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700386 size_t i;
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700387 grpc_channel_stack *client_stack;
388 grpc_channel_element *client_channel_filter;
389 grpc_connectivity_state actual_conn_state;
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700390 va_list ap;
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700391
392 client_stack = grpc_channel_get_channel_stack(ch);
393 client_channel_filter = grpc_channel_stack_last_element(client_stack);
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700394
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700395 actual_conn_state = grpc_client_channel_check_connectivity_state(
396 client_channel_filter, 0 /* don't try to connect */);
David Garcia Quintas56d66c22015-09-11 22:19:18 -0700397 va_start(ap, accepted_conn_state);
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700398 for (i = 0; i < num_accepted_conn_states; i++) {
David Garcia Quintas56d66c22015-09-11 22:19:18 -0700399 if (actual_conn_state == accepted_conn_state) {
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700400 break;
401 }
David Garcia Quintas56d66c22015-09-11 22:19:18 -0700402 accepted_conn_state = va_arg(ap, grpc_connectivity_state);
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700403 }
404 va_end(ap);
405 if (i == num_accepted_conn_states) {
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700406 char **accepted_strs =
407 gpr_malloc(sizeof(char *) * num_accepted_conn_states);
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700408 char *accepted_str_joined;
David Garcia Quintas56d66c22015-09-11 22:19:18 -0700409 va_start(ap, accepted_conn_state);
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700410 for (i = 0; i < num_accepted_conn_states; i++) {
David Garcia Quintas56d66c22015-09-11 22:19:18 -0700411 GPR_ASSERT(gpr_asprintf(&accepted_strs[i], "%d", accepted_conn_state) >
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700412 0);
David Garcia Quintas56d66c22015-09-11 22:19:18 -0700413 accepted_conn_state = va_arg(ap, grpc_connectivity_state);
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700414 }
415 va_end(ap);
416 accepted_str_joined = gpr_strjoin_sep((const char **)accepted_strs,
417 num_accepted_conn_states, ", ", NULL);
418 gpr_log(
419 GPR_ERROR,
420 "Channel connectivity assertion failed: expected <one of [%s]>, got %d",
421 accepted_str_joined, actual_conn_state);
422
423 for (i = 0; i < num_accepted_conn_states; i++) {
424 gpr_free(accepted_strs[i]);
425 }
426 gpr_free(accepted_strs);
427 gpr_free(accepted_str_joined);
428 abort();
429 }
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700430}
431
432void run_spec(const test_spec *spec) {
433 grpc_channel *client;
434 char *client_hostport;
435 char *servers_hostports_str;
436 int *actual_connection_sequence;
437 servers_fixture *f = setup_servers("127.0.0.1", spec->num_servers);
438
439 /* Create client. */
440 servers_hostports_str = gpr_strjoin_sep((const char **)f->servers_hostports,
441 f->num_servers, ",", NULL);
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700442 gpr_asprintf(&client_hostport, "ipv4:%s?lb_policy=round_robin",
443 servers_hostports_str);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700444 client = grpc_insecure_channel_create(client_hostport, NULL, NULL);
445
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700446 gpr_log(GPR_INFO, "Testing '%s' with servers=%s client=%s", spec->description,
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700447 servers_hostports_str, client_hostport);
448
449 actual_connection_sequence = perform_request(f, client, spec);
450
451 spec->verifier(f, client, actual_connection_sequence, spec->num_iters);
452
453 gpr_free(client_hostport);
454 gpr_free(servers_hostports_str);
455 gpr_free(actual_connection_sequence);
456
457 grpc_channel_destroy(client);
458 teardown_servers(f);
459}
460
461static void print_failed_expectations(const int *expected_connection_sequence,
462 const int *actual_connection_sequence,
463 const size_t expected_seq_length,
464 const size_t num_iters) {
465 size_t i;
466 for (i = 0; i < num_iters; i++) {
467 gpr_log(GPR_ERROR, "FAILURE: Iter, expected, actual:%d (%d, %d)", i,
468 expected_connection_sequence[i % expected_seq_length],
469 actual_connection_sequence[i]);
470 }
471}
472
473static void verify_vanilla_round_robin(const servers_fixture *f,
474 grpc_channel *client,
475 const int *actual_connection_sequence,
476 const size_t num_iters) {
477 int *expected_connection_sequence;
478 size_t i;
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700479 const size_t expected_seq_length = f->num_servers;
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700480
481 /* verify conn. seq. expectation */
482 /* get the first sequence of "num_servers" elements */
483 expected_connection_sequence = gpr_malloc(sizeof(int) * expected_seq_length);
484 memcpy(expected_connection_sequence, actual_connection_sequence,
485 sizeof(int) * expected_seq_length);
486
487 for (i = 0; i < num_iters; i++) {
488 const int actual = actual_connection_sequence[i];
489 const int expected = expected_connection_sequence[i % expected_seq_length];
490 if (actual != expected) {
491 gpr_log(GPR_ERROR, "FAILURE: expected %d, actual %d at iter %d", expected,
492 actual, i);
493 print_failed_expectations(expected_connection_sequence,
494 actual_connection_sequence, expected_seq_length,
495 num_iters);
496 abort();
497 }
498 }
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700499 assert_channel_connectivity(client, 1, GRPC_CHANNEL_READY);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700500
501 gpr_free(expected_connection_sequence);
502}
503
504/* At the start of the second iteration, all but the first and last servers (as
505 * given in "f") are killed */
506static void verify_vanishing_floor_round_robin(
507 const servers_fixture *f, grpc_channel *client,
508 const int *actual_connection_sequence, const size_t num_iters) {
509 int *expected_connection_sequence;
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700510 const size_t expected_seq_length = 2;
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700511 size_t i;
512
513 /* verify conn. seq. expectation */
514 /* copy the first full sequence (without -1s) */
515 expected_connection_sequence = gpr_malloc(sizeof(int) * expected_seq_length);
516 memcpy(expected_connection_sequence, actual_connection_sequence + 2,
517 expected_seq_length * sizeof(int));
518
519 /* first three elements of the sequence should be [<1st>, -1] */
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700520 if (actual_connection_sequence[0] != expected_connection_sequence[0]) {
521 gpr_log(GPR_ERROR, "FAILURE: expected %d, actual %d at iter %d",
522 expected_connection_sequence[0], actual_connection_sequence[0], 0);
523 print_failed_expectations(expected_connection_sequence,
524 actual_connection_sequence, expected_seq_length,
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700525 1u);
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700526 abort();
527 }
528
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700529 GPR_ASSERT(actual_connection_sequence[1] == -1);
530
531 for (i = 2; i < num_iters; i++) {
532 const int actual = actual_connection_sequence[i];
533 const int expected = expected_connection_sequence[i % expected_seq_length];
534 if (actual != expected) {
535 gpr_log(GPR_ERROR, "FAILURE: expected %d, actual %d at iter %d", expected,
536 actual, i);
537 print_failed_expectations(expected_connection_sequence,
538 actual_connection_sequence, expected_seq_length,
539 num_iters);
540 abort();
541 }
542 }
543 gpr_free(expected_connection_sequence);
544}
545
546static void verify_total_carnage_round_robin(
547 const servers_fixture *f, grpc_channel *client,
548 const int *actual_connection_sequence, const size_t num_iters) {
549 size_t i;
550
551 for (i = 0; i < num_iters; i++) {
552 const int actual = actual_connection_sequence[i];
553 const int expected = -1;
554 if (actual != expected) {
555 gpr_log(GPR_ERROR, "FAILURE: expected %d, actual %d at iter %d", expected,
556 actual, i);
557 abort();
558 }
559 }
560
561 /* even though we know all the servers are dead, the client is still trying
562 * retrying, believing it's in a transient failure situation */
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700563 assert_channel_connectivity(client, 2, GRPC_CHANNEL_TRANSIENT_FAILURE,
564 GRPC_CHANNEL_CONNECTING);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700565}
566
567static void verify_partial_carnage_round_robin(
568 const servers_fixture *f, grpc_channel *client,
569 const int *actual_connection_sequence, const size_t num_iters) {
570 int *expected_connection_sequence;
571 size_t i;
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700572 const size_t expected_seq_length = f->num_servers;
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700573
574 /* verify conn. seq. expectation */
575 /* get the first sequence of "num_servers" elements */
576 expected_connection_sequence = gpr_malloc(sizeof(int) * expected_seq_length);
577 memcpy(expected_connection_sequence, actual_connection_sequence,
578 sizeof(int) * expected_seq_length);
579
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700580 for (i = 0; i < num_iters / 2; i++) {
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700581 const int actual = actual_connection_sequence[i];
582 const int expected = expected_connection_sequence[i % expected_seq_length];
583 if (actual != expected) {
584 gpr_log(GPR_ERROR, "FAILURE: expected %d, actual %d at iter %d", expected,
585 actual, i);
586 print_failed_expectations(expected_connection_sequence,
587 actual_connection_sequence, expected_seq_length,
588 num_iters);
589 abort();
590 }
591 }
592
593 /* second half of the iterations go without response */
594 for (; i < num_iters; i++) {
595 GPR_ASSERT(actual_connection_sequence[i] == -1);
596 }
597
598 /* even though we know all the servers are dead, the client is still trying
599 * retrying, believing it's in a transient failure situation */
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700600 assert_channel_connectivity(client, 2, GRPC_CHANNEL_TRANSIENT_FAILURE,
601 GRPC_CHANNEL_CONNECTING);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700602 gpr_free(expected_connection_sequence);
603}
604
605static void verify_rebirth_round_robin(const servers_fixture *f,
606 grpc_channel *client,
607 const int *actual_connection_sequence,
608 const size_t num_iters) {
609 int *expected_connection_sequence;
610 size_t i;
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700611 const size_t expected_seq_length = f->num_servers;
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700612
613 /* verify conn. seq. expectation */
614 /* get the first sequence of "num_servers" elements */
615 expected_connection_sequence = gpr_malloc(sizeof(int) * expected_seq_length);
616 memcpy(expected_connection_sequence, actual_connection_sequence + 4,
617 sizeof(int) * expected_seq_length);
618
619 /* first iteration succeeds */
620 GPR_ASSERT(actual_connection_sequence[0] != -1);
621
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700622 /* back up on the third (or maybe fourth) iteration */
623 i = 3;
624 if (actual_connection_sequence[i] == -1) {
625 i = 4;
626 }
627 for (; i < num_iters; i++) {
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700628 const int actual = actual_connection_sequence[i];
629 const int expected = expected_connection_sequence[i % expected_seq_length];
630 if (actual != expected) {
631 gpr_log(GPR_ERROR, "FAILURE: expected %d, actual %d at iter %d", expected,
632 actual, i);
633 print_failed_expectations(expected_connection_sequence,
634 actual_connection_sequence, expected_seq_length,
635 num_iters);
636 abort();
637 }
638 }
639
640 /* things are fine once the servers are brought back up */
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700641 assert_channel_connectivity(client, 1, GRPC_CHANNEL_READY);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700642 gpr_free(expected_connection_sequence);
643}
644
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700645int main(int argc, char **argv) {
646 test_spec *spec;
647 size_t i;
648 const size_t NUM_ITERS = 10;
649 const size_t NUM_SERVERS = 4;
650
651 grpc_test_init(argc, argv);
652 grpc_init();
653
654 /* everything is fine, all servers stay up the whole time and life's peachy */
655 spec = test_spec_create(NUM_ITERS, NUM_SERVERS);
656 spec->verifier = verify_vanilla_round_robin;
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700657 spec->description = "test_all_server_up";
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700658 run_spec(spec);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700659
660 /* Kill all servers first thing in the morning */
661 test_spec_reset(spec);
662 spec->verifier = verify_total_carnage_round_robin;
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700663 spec->description = "test_kill_all_server";
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700664 for (i = 0; i < NUM_SERVERS; i++) {
665 spec->kill_at[0][i] = 1;
666 }
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700667 run_spec(spec);
668
669 /* at the start of the 2nd iteration, kill all but the first and last servers.
670 * This should knock down the server bound to be selected next */
671 test_spec_reset(spec);
672 spec->verifier = verify_vanishing_floor_round_robin;
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700673 spec->description = "test_kill_all_server_at_2nd_iteration";
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700674 for (i = 1; i < NUM_SERVERS - 1; i++) {
675 spec->kill_at[1][i] = 1;
676 }
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700677 run_spec(spec);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700678
679 /* Midway, kill all servers. */
680 test_spec_reset(spec);
681 spec->verifier = verify_partial_carnage_round_robin;
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700682 spec->description = "test_kill_all_server_midway";
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700683 for (i = 0; i < NUM_SERVERS; i++) {
684 spec->kill_at[spec->num_iters / 2][i] = 1;
685 }
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700686 run_spec(spec);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700687
688 /* After first iteration, kill all servers. On the third one, bring them all
689 * back up. */
690 test_spec_reset(spec);
691 spec->verifier = verify_rebirth_round_robin;
David Garcia Quintasfe7a6362015-09-10 11:06:46 -0700692 spec->description = "test_kill_all_server_after_1st_resurrect_at_3rd";
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700693 for (i = 0; i < NUM_SERVERS; i++) {
694 spec->kill_at[1][i] = 1;
695 spec->revive_at[3][i] = 1;
696 }
David Garcia Quintasa4c43a62015-09-11 13:33:57 -0700697 run_spec(spec);
David Garcia Quintas4fb049b2015-09-03 17:26:06 -0700698
699 test_spec_destroy(spec);
700
701 grpc_shutdown();
702 return 0;
703}