]> git.meshlink.io Git - meshlink/blob - test/blackbox/run_blackbox_tests/test_cases_channel_shutdown.c
Fix __warn_unused_result__, add more of it and fix the resulting warnings.
[meshlink] / test / blackbox / run_blackbox_tests / test_cases_channel_shutdown.c
1 /*
2     test_cases_channel_shutdown.c -- Execution of specific meshlink black box test cases
3     Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifdef NDEBUG
21 #undef NDEBUG
22 #endif
23
24 #include "execute_tests.h"
25 #include "test_cases_channel_shutdown.h"
26 #include "../common/containers.h"
27 #include "../common/test_step.h"
28 #include "../common/common_handlers.h"
29 #include <assert.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <setjmp.h>
34 #include <cmocka.h>
35 #include <pthread.h>
36
37 /* Modify this to change the logging level of Meshlink */
38 #define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
39
40 static void test_case_mesh_channel_shutdown_01(void **state);
41 static bool test_steps_mesh_channel_shutdown_01(void);
42 static void test_case_mesh_channel_shutdown_02(void **state);
43 static bool test_steps_mesh_channel_shutdown_02(void);
44 static void test_case_mesh_channel_shutdown_03(void **state);
45 static bool test_steps_mesh_channel_shutdown_03(void);
46
47 static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len);
48 static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len);
49
50 /* State structure for meshlink_channel_shutdown Test Case #1 */
51 static black_box_state_t test_mesh_channel_shutdown_01_state = {
52         .test_case_name = "test_case_mesh_channel_shutdown_01",
53 };
54
55 /* State structure for meshlink_channel_shutdown Test Case #2 */
56 static black_box_state_t test_mesh_channel_shutdown_02_state = {
57         .test_case_name = "test_case_mesh_channel_shutdown_02",
58 };
59
60 /* State structure for meshlink_channel_shutdown Test Case #3 */
61 static black_box_state_t test_mesh_channel_shutdown_03_state = {
62         .test_case_name = "test_case_mesh_channel_shutdown_03",
63 };
64
65 static bool channel_acc;
66 static bool polled;
67 static bool foo_responded;
68 static bool bar_responded;
69
70 /* mutex for the common variable */
71 static pthread_mutex_t accept_lock = PTHREAD_MUTEX_INITIALIZER;
72 static pthread_mutex_t poll_lock = PTHREAD_MUTEX_INITIALIZER;
73 static pthread_mutex_t bar_responded_lock = PTHREAD_MUTEX_INITIALIZER;
74 static pthread_mutex_t foo_responded_lock = PTHREAD_MUTEX_INITIALIZER;
75
76 static pthread_cond_t accept_cond = PTHREAD_COND_INITIALIZER;
77 static pthread_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
78 static pthread_cond_t foo_cond = PTHREAD_COND_INITIALIZER;
79 static pthread_cond_t bar_cond = PTHREAD_COND_INITIALIZER;
80
81 static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
82         (void)data;
83
84         assert(port == 7);
85         assert(!len);
86
87         meshlink_set_channel_receive_cb(mesh, channel, receive_cb);
88         channel->node->priv = channel;
89         pthread_mutex_lock(&accept_lock);
90         channel_acc = true;
91         assert(!pthread_cond_broadcast(&accept_cond));
92         pthread_mutex_unlock(&accept_lock);
93
94         return true;
95 }
96
97 /* channel receive callback */
98 static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) {
99         (void)dat;
100         (void)len;
101
102         if(!strcmp(mesh->name, "foo")) {
103                 pthread_mutex_lock(& foo_responded_lock);
104                 foo_responded = true;
105                 assert(!pthread_cond_broadcast(&foo_cond));
106                 pthread_mutex_unlock(& foo_responded_lock);
107
108         } else if(!strcmp(mesh->name, "bar")) {
109                 pthread_mutex_lock(& bar_responded_lock);
110                 bar_responded = true;
111                 assert(!pthread_cond_broadcast(&bar_cond));
112                 pthread_mutex_unlock(& bar_responded_lock);
113
114                 assert(meshlink_channel_send(mesh, channel, "echo", 4) >= 0);
115
116         }
117 }
118
119 static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
120         (void)len;
121
122         meshlink_set_channel_poll_cb(mesh, channel, NULL);
123         pthread_mutex_lock(&poll_lock);
124         polled = true;
125         assert(!pthread_cond_broadcast(&poll_cond));
126         pthread_mutex_unlock(&poll_lock);
127 }
128
129 /* Execute meshlink_channel_shutdown Test Case # 1*/
130 static void test_case_mesh_channel_shutdown_01(void **state) {
131         execute_test(test_steps_mesh_channel_shutdown_01, state);
132 }
133
134 /* Test Steps for meshlink_channel_shutdown Test Case # 1 - Valid case
135
136     Test Steps:
137     1. Open foo and bar instances and open a channel between them
138     2. Send data through the channel.
139     3. Shut down channel's read and send data
140     4. Shutdown channel's write and send data
141
142     Expected Result:
143     Data is able to receive through channel before shutting down,
144     On shutting down read its should not able to receive data and when write
145     is shut down its should be able to send data through channel.
146 */
147 static bool test_steps_mesh_channel_shutdown_01(void) {
148         struct timespec timeout = {0};
149         assert(meshlink_destroy("chan_shutdown_conf.1"));
150         assert(meshlink_destroy("chan_shutdown_conf.2"));
151         // Open two new meshlink instance.
152
153         meshlink_handle_t *mesh1 = meshlink_open("chan_shutdown_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
154         assert(mesh1 != NULL);
155
156         meshlink_handle_t *mesh2 = meshlink_open("chan_shutdown_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
157         assert(mesh2 != NULL);
158
159         char *data = meshlink_export(mesh1);
160         assert(data);
161         assert(meshlink_import(mesh2, data));
162         free(data);
163         data = meshlink_export(mesh2);
164         assert(data);
165         assert(meshlink_import(mesh1, data));
166         free(data);
167
168         // Set the callbacks.
169
170         meshlink_set_channel_accept_cb(mesh2, accept_cb);
171
172         // Start both instances
173
174         assert(meshlink_start(mesh1));
175         assert(meshlink_start(mesh2));
176         sleep(1);
177
178         // Open a channel from foo to bar.
179
180         meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
181         assert(bar);
182
183         meshlink_channel_t *channel1 = meshlink_channel_open(mesh1, bar, 7, receive_cb, NULL, 0);
184         meshlink_set_channel_poll_cb(mesh1, channel1, poll_cb);
185
186         timeout.tv_sec = time(NULL) + 10;
187         pthread_mutex_lock(&poll_lock);
188
189         while(polled == false) {
190                 assert(!pthread_cond_timedwait(&poll_cond, &poll_lock, &timeout));
191         }
192
193         pthread_mutex_unlock(&poll_lock);
194
195         timeout.tv_sec = time(NULL) + 10;
196         pthread_mutex_lock(&accept_lock);
197
198         while(channel_acc == false) {
199                 assert(!pthread_cond_timedwait(&accept_cond, &accept_lock, &timeout));
200         }
201
202         pthread_mutex_unlock(&accept_lock);
203
204         // Sending to bar and testing the echo
205
206         assert(meshlink_channel_send(mesh1, channel1, "echo", 4) >= 0);
207
208         timeout.tv_sec = time(NULL) + 10;
209         pthread_mutex_lock(&foo_responded_lock);
210
211         while(foo_responded == false) {
212                 assert(!pthread_cond_timedwait(&foo_cond, &foo_responded_lock, &timeout));
213         }
214
215         pthread_mutex_unlock(&foo_responded_lock);
216         assert(foo_responded);
217
218         // Shutting down channel read
219
220         meshlink_channel_shutdown(mesh1, channel1, SHUT_RD);
221         bar_responded = false;
222         foo_responded = false;
223         assert(meshlink_channel_send(mesh1, channel1, "echo", 4) >= 0);
224
225         timeout.tv_sec = time(NULL) + 10;
226         pthread_mutex_lock(&bar_responded_lock);
227
228         while(bar_responded == false) {
229                 assert(!pthread_cond_timedwait(&bar_cond, &bar_responded_lock, &timeout));
230         }
231
232         pthread_mutex_unlock(&bar_responded_lock);
233         assert_int_equal(bar_responded, true);
234         sleep(1);
235         assert_int_equal(foo_responded, false);
236
237         // Shutting down channel write
238
239         meshlink_channel_shutdown(mesh1, channel1, SHUT_WR);
240
241         ssize_t send_ret = meshlink_channel_send(mesh1, channel1, "echo", 4);
242         assert_int_equal(send_ret, -1);
243
244         // Clean up.
245
246         meshlink_close(mesh2);
247         meshlink_close(mesh1);
248         assert(meshlink_destroy("chan_shutdown_conf.1"));
249         assert(meshlink_destroy("chan_shutdown_conf.2"));
250
251         return true;
252 }
253
254 /* Execute meshlink_channel_shutdown Test Case # 2*/
255 static void test_case_mesh_channel_shutdown_02(void **state) {
256         execute_test(test_steps_mesh_channel_shutdown_02, state);
257 }
258
259 /* Test Steps for meshlink_channel_shutdown Test Case # 2 - Invalid case
260
261     Test Steps:
262     1. Open node instance and create a channel
263     2. Call meshlink_channel_shutdown API by passing NULL as mesh handle
264
265     Expected Result:
266     meshlink_channel_shutdown API should report proper error handling
267 */
268 static bool test_steps_mesh_channel_shutdown_02(void) {
269         assert(meshlink_destroy("channelshutdownconf.3"));
270         meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
271
272         /* Create meshlink instance */
273         meshlink_handle_t *mesh_handle = meshlink_open("channelshutdownconf.3", "nut", "node_sim", 1);
274         assert(mesh_handle != NULL);
275         meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
276         meshlink_set_channel_accept_cb(mesh_handle, accept_cb);
277
278         assert(meshlink_start(mesh_handle));
279
280         meshlink_node_t *node = meshlink_get_self(mesh_handle);
281         assert(node != NULL);
282
283         meshlink_channel_t *channel = meshlink_channel_open(mesh_handle, node, 8000, NULL, NULL, 0);
284         assert(channel);
285         meshlink_set_channel_poll_cb(mesh_handle, channel, poll_cb);
286
287         // Passing NULL as mesh handle and other arguments being valid
288
289         meshlink_channel_shutdown(NULL, channel, SHUT_WR);
290         assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
291
292         meshlink_close(mesh_handle);
293         assert(meshlink_destroy("channelshutdownconf.3"));
294
295         return true;
296 }
297
298 /* Execute meshlink_channel_shutdown Test Case # 3*/
299 static void test_case_mesh_channel_shutdown_03(void **state) {
300         execute_test(test_steps_mesh_channel_shutdown_03, state);
301 }
302
303 /* Test Steps for meshlink_channel_shutdown Test Case # 3
304
305     Test Steps:
306     1. Open node instance
307     2. Call meshlink_channel_shutdown API by passing NULL as channel handle
308
309     Expected Result:
310     meshlink_channel_shutdown API should report proper error handling
311 */
312 static bool test_steps_mesh_channel_shutdown_03(void) {
313         assert(meshlink_destroy("channelshutdownconf.4"));
314         meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
315
316         /* Create meshlink instance */
317         meshlink_handle_t *mesh_handle = meshlink_open("channelshutdownconf.4", "nut", "node_sim", 1);
318         assert(mesh_handle != NULL);
319         meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
320         meshlink_set_channel_accept_cb(mesh_handle, accept_cb);
321
322         assert(meshlink_start(mesh_handle));
323
324         // Passing NULL as mesh handle and other arguments being valid
325
326         meshlink_channel_shutdown(mesh_handle, NULL, SHUT_WR);
327         assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
328
329         meshlink_close(mesh_handle);
330         assert(meshlink_destroy("channelshutdownconf.4"));
331
332         return true;
333 }
334
335
336 int test_meshlink_channel_shutdown(void) {
337         const struct CMUnitTest blackbox_channel_shutdown_tests[] = {
338                 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_shutdown_01, NULL, NULL,
339                                 (void *)&test_mesh_channel_shutdown_01_state),
340                 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_shutdown_02, NULL, NULL,
341                                 (void *)&test_mesh_channel_shutdown_02_state),
342                 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_shutdown_03, NULL, NULL,
343                                 (void *)&test_mesh_channel_shutdown_03_state)
344         };
345         total_tests += sizeof(blackbox_channel_shutdown_tests) / sizeof(blackbox_channel_shutdown_tests[0]);
346
347         return cmocka_run_group_tests(blackbox_channel_shutdown_tests, NULL, NULL);
348 }