blob: 5b05ea3338ab831b12e13b615c354e5bc5f06d05 [file] [log] [blame]
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -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 */
murgatroid9954070892016-08-08 17:01:18 -070033#include "src/core/lib/iomgr/port.h"
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070034
Sree Kuchibhotla76a07952016-06-22 15:09:06 -070035/* This test only relevant on linux systems where epoll() is available */
murgatroid99623dd4f2016-08-08 17:31:27 -070036#ifdef GRPC_LINUX_EPOLL
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070037#include "src/core/lib/iomgr/ev_epoll_linux.h"
38#include "src/core/lib/iomgr/ev_posix.h"
39
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -070040#include <errno.h>
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070041#include <string.h>
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070042#include <unistd.h>
43
44#include <grpc/support/alloc.h>
45#include <grpc/support/log.h>
46
47#include "src/core/lib/iomgr/iomgr.h"
Harvey Tuchdaa9f452016-11-21 15:42:49 -050048#include "src/core/lib/iomgr/workqueue.h"
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070049#include "test/core/util/test_config.h"
50
51typedef struct test_pollset {
52 grpc_pollset *pollset;
53 gpr_mu *mu;
54} test_pollset;
55
56typedef struct test_fd {
57 int inner_fd;
58 grpc_fd *fd;
59} test_fd;
60
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -070061/* num_fds should be an even number */
62static void test_fd_init(test_fd *tfds, int *fds, int num_fds) {
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070063 int i;
Harvey Tuchdaa9f452016-11-21 15:42:49 -050064 int r;
65
66 /* Create some dummy file descriptors. Currently using pipe file descriptors
67 * for this test but we could use any other type of file descriptors. Also,
68 * since pipe() used in this test creates two fds in each call, num_fds should
69 * be an even number */
70 GPR_ASSERT((num_fds % 2) == 0);
71 for (i = 0; i < num_fds; i = i + 2) {
72 r = pipe(fds + i);
73 if (r != 0) {
74 gpr_log(GPR_ERROR, "Error in creating pipe. %d (%s)", errno,
75 strerror(errno));
76 return;
77 }
78 }
79
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070080 for (i = 0; i < num_fds; i++) {
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -070081 tfds[i].inner_fd = fds[i];
82 tfds[i].fd = grpc_fd_create(fds[i], "test_fd");
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070083 }
84}
85
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -070086static void test_fd_cleanup(grpc_exec_ctx *exec_ctx, test_fd *tfds,
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070087 int num_fds) {
88 int release_fd;
89 int i;
90
91 for (i = 0; i < num_fds; i++) {
Craig Tillercda759d2017-01-27 11:37:37 -080092 grpc_fd_shutdown(exec_ctx, tfds[i].fd,
93 GRPC_ERROR_CREATE("test_fd_cleanup"));
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070094 grpc_exec_ctx_flush(exec_ctx);
95
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -070096 grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, "test_fd_cleanup");
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -070097 grpc_exec_ctx_flush(exec_ctx);
98
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -070099 GPR_ASSERT(release_fd == tfds[i].inner_fd);
100 close(tfds[i].inner_fd);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700101 }
102}
103
104static void test_pollset_init(test_pollset *pollsets, int num_pollsets) {
105 int i;
106 for (i = 0; i < num_pollsets; i++) {
107 pollsets[i].pollset = gpr_malloc(grpc_pollset_size());
108 grpc_pollset_init(pollsets[i].pollset, &pollsets[i].mu);
109 }
110}
111
Sree Kuchibhotla3131c262016-06-21 17:28:28 -0700112static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
113 grpc_error *error) {
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700114 grpc_pollset_destroy(p);
115}
116
117static void test_pollset_cleanup(grpc_exec_ctx *exec_ctx,
118 test_pollset *pollsets, int num_pollsets) {
119 grpc_closure destroyed;
120 int i;
121
122 for (i = 0; i < num_pollsets; i++) {
Craig Tillerd4654562017-01-03 08:45:56 -0800123 grpc_closure_init(&destroyed, destroy_pollset, pollsets[i].pollset,
124 grpc_schedule_on_exec_ctx);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700125 grpc_pollset_shutdown(exec_ctx, pollsets[i].pollset, &destroyed);
126
127 grpc_exec_ctx_flush(exec_ctx);
128 gpr_free(pollsets[i].pollset);
129 }
130}
131
Harvey Tuchdaa9f452016-11-21 15:42:49 -0500132static void increment(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
133 ++*(int *)arg;
134}
135
136/*
137 * Validate that merging two workqueues preserves the closures in each queue.
138 * This is a regression test for a bug in
139 * polling_island_merge()[ev_epoll_linux.c], where the parent relationship was
140 * inverted.
141 */
142static void test_pollset_queue_merge_items() {
143 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
144 const int num_fds = 2;
145 const int num_pollsets = 2;
146 const int num_closures = 4;
147 test_fd tfds[num_fds];
148 int fds[num_fds];
149 test_pollset pollsets[num_pollsets];
150 grpc_closure closures[num_closures];
151 int i;
152 int result = 0;
153
154 test_fd_init(tfds, fds, num_fds);
155 test_pollset_init(pollsets, num_pollsets);
156
157 /* Two distinct polling islands, each with their own FD and pollset. */
158 for (i = 0; i < num_fds; i++) {
159 grpc_pollset_add_fd(&exec_ctx, pollsets[i].pollset, tfds[i].fd);
160 grpc_exec_ctx_flush(&exec_ctx);
161 }
162
163 /* Enqeue the closures, 3 to polling island 0 and 1 to polling island 1. */
164 grpc_closure_init(
165 closures, increment, &result,
166 grpc_workqueue_scheduler(grpc_fd_get_polling_island(tfds[0].fd)));
167 grpc_closure_init(
168 closures + 1, increment, &result,
169 grpc_workqueue_scheduler(grpc_fd_get_polling_island(tfds[0].fd)));
170 grpc_closure_init(
171 closures + 2, increment, &result,
172 grpc_workqueue_scheduler(grpc_fd_get_polling_island(tfds[0].fd)));
173 grpc_closure_init(
174 closures + 3, increment, &result,
175 grpc_workqueue_scheduler(grpc_fd_get_polling_island(tfds[1].fd)));
176 for (i = 0; i < num_closures; ++i) {
177 grpc_closure_sched(&exec_ctx, closures + i, GRPC_ERROR_NONE);
178 }
179
180 /* Merge the two polling islands. */
181 grpc_pollset_add_fd(&exec_ctx, pollsets[0].pollset, tfds[1].fd);
182 grpc_exec_ctx_flush(&exec_ctx);
183
184 /*
185 * Execute the closures, verify we see each one execute when executing work on
186 * the merged polling island.
187 */
188 grpc_pollset_worker *worker = NULL;
189 for (i = 0; i < num_closures; ++i) {
190 const gpr_timespec deadline = gpr_time_add(
191 gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(2, GPR_TIMESPAN));
192 gpr_mu_lock(pollsets[1].mu);
193 GRPC_LOG_IF_ERROR(
194 "grpc_pollset_work",
195 grpc_pollset_work(&exec_ctx, pollsets[1].pollset, &worker,
196 gpr_now(GPR_CLOCK_MONOTONIC), deadline));
197 gpr_mu_unlock(pollsets[1].mu);
198 }
199 GPR_ASSERT(result == num_closures);
200
201 test_fd_cleanup(&exec_ctx, tfds, num_fds);
202 test_pollset_cleanup(&exec_ctx, pollsets, num_pollsets);
203 grpc_exec_ctx_finish(&exec_ctx);
204}
205
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700206/*
207 * Cases to test:
208 * case 1) Polling islands of both fd and pollset are NULL
209 * case 2) Polling island of fd is NULL but that of pollset is not-NULL
210 * case 3) Polling island of fd is not-NULL but that of pollset is NULL
211 * case 4) Polling islands of both fd and pollset are not-NULL and:
212 * case 4.1) Polling islands of fd and pollset are equal
213 * case 4.2) Polling islands of fd and pollset are NOT-equal (This results
214 * in a merge)
215 * */
216static void test_add_fd_to_pollset() {
217 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Harvey Tuchdaa9f452016-11-21 15:42:49 -0500218 const int num_fds = 8;
219 const int num_pollsets = 4;
220 test_fd tfds[num_fds];
221 int fds[num_fds];
222 test_pollset pollsets[num_pollsets];
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700223 void *expected_pi = NULL;
224 int i;
225
Harvey Tuchdaa9f452016-11-21 15:42:49 -0500226 test_fd_init(tfds, fds, num_fds);
227 test_pollset_init(pollsets, num_pollsets);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700228
229 /*Step 1.
230 * Create three polling islands (This will exercise test case 1 and 2) with
231 * the following configuration:
232 * polling island 0 = { fds:0,1,2, pollsets:0}
233 * polling island 1 = { fds:3,4, pollsets:1}
234 * polling island 2 = { fds:5,6,7 pollsets:2}
235 *
236 *Step 2.
237 * Add pollset 3 to polling island 0 (by adding fds 0 and 1 to pollset 3)
238 * (This will exercise test cases 3 and 4.1). The configuration becomes:
239 * polling island 0 = { fds:0,1,2, pollsets:0,3} <<< pollset 3 added here
240 * polling island 1 = { fds:3,4, pollsets:1}
241 * polling island 2 = { fds:5,6,7 pollsets:2}
242 *
243 *Step 3.
244 * Merge polling islands 0 and 1 by adding fd 0 to pollset 1 (This will
245 * exercise test case 4.2). The configuration becomes:
246 * polling island (merged) = {fds: 0,1,2,3,4, pollsets: 0,1,3}
247 * polling island 2 = {fds: 5,6,7 pollsets: 2}
248 *
249 *Step 4.
250 * Finally do one more merge by adding fd 3 to pollset 2.
251 * polling island (merged) = {fds: 0,1,2,3,4,5,6,7, pollsets: 0,1,2,3}
252 */
253
254 /* == Step 1 == */
255 for (i = 0; i <= 2; i++) {
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -0700256 grpc_pollset_add_fd(&exec_ctx, pollsets[0].pollset, tfds[i].fd);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700257 grpc_exec_ctx_flush(&exec_ctx);
258 }
259
260 for (i = 3; i <= 4; i++) {
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -0700261 grpc_pollset_add_fd(&exec_ctx, pollsets[1].pollset, tfds[i].fd);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700262 grpc_exec_ctx_flush(&exec_ctx);
263 }
264
265 for (i = 5; i <= 7; i++) {
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -0700266 grpc_pollset_add_fd(&exec_ctx, pollsets[2].pollset, tfds[i].fd);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700267 grpc_exec_ctx_flush(&exec_ctx);
268 }
269
270 /* == Step 2 == */
271 for (i = 0; i <= 1; i++) {
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -0700272 grpc_pollset_add_fd(&exec_ctx, pollsets[3].pollset, tfds[i].fd);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700273 grpc_exec_ctx_flush(&exec_ctx);
274 }
275
276 /* == Step 3 == */
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -0700277 grpc_pollset_add_fd(&exec_ctx, pollsets[1].pollset, tfds[0].fd);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700278 grpc_exec_ctx_flush(&exec_ctx);
279
280 /* == Step 4 == */
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -0700281 grpc_pollset_add_fd(&exec_ctx, pollsets[2].pollset, tfds[3].fd);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700282 grpc_exec_ctx_flush(&exec_ctx);
283
284 /* All polling islands are merged at this point */
285
286 /* Compare Fd:0's polling island with that of all other Fds */
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -0700287 expected_pi = grpc_fd_get_polling_island(tfds[0].fd);
Harvey Tuchdaa9f452016-11-21 15:42:49 -0500288 for (i = 1; i < num_fds; i++) {
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700289 GPR_ASSERT(grpc_are_polling_islands_equal(
Sree Kuchibhotlaa2dd8382016-06-22 10:26:03 -0700290 expected_pi, grpc_fd_get_polling_island(tfds[i].fd)));
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700291 }
292
293 /* Compare Fd:0's polling island with that of all other pollsets */
Harvey Tuchdaa9f452016-11-21 15:42:49 -0500294 for (i = 0; i < num_pollsets; i++) {
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700295 GPR_ASSERT(grpc_are_polling_islands_equal(
296 expected_pi, grpc_pollset_get_polling_island(pollsets[i].pollset)));
297 }
298
Harvey Tuchdaa9f452016-11-21 15:42:49 -0500299 test_fd_cleanup(&exec_ctx, tfds, num_fds);
300 test_pollset_cleanup(&exec_ctx, pollsets, num_pollsets);
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700301 grpc_exec_ctx_finish(&exec_ctx);
302}
303
304int main(int argc, char **argv) {
305 const char *poll_strategy = NULL;
306 grpc_test_init(argc, argv);
307 grpc_iomgr_init();
308
309 poll_strategy = grpc_get_poll_strategy_name();
310 if (poll_strategy != NULL && strcmp(poll_strategy, "epoll") == 0) {
311 test_add_fd_to_pollset();
Harvey Tuchdaa9f452016-11-21 15:42:49 -0500312 test_pollset_queue_merge_items();
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700313 } else {
314 gpr_log(GPR_INFO,
315 "Skipping the test. The test is only relevant for 'epoll' "
316 "strategy. and the current strategy is: '%s'",
317 poll_strategy);
318 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800319
Craig Tiller7885d1a2016-11-17 14:07:45 -0800320 {
321 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
322 grpc_iomgr_shutdown(&exec_ctx);
323 grpc_exec_ctx_finish(&exec_ctx);
324 }
Sree Kuchibhotla2e12db92016-06-16 16:53:59 -0700325 return 0;
326}
murgatroid99623dd4f2016-08-08 17:31:27 -0700327#else /* defined(GRPC_LINUX_EPOLL) */
Sree Kuchibhotlafcb304f2016-06-22 15:25:41 -0700328int main(int argc, char **argv) { return 0; }
murgatroid99623dd4f2016-08-08 17:31:27 -0700329#endif /* !defined(GRPC_LINUX_EPOLL) */