2 test_cases_channel_shutdown.c -- Execution of specific meshlink black box test cases
3 Copyright (C) 2018 Guus Sliepen <guus@meshlink.io>
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.
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.
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.
20 #include "execute_tests.h"
21 #include "test_cases_channel_shutdown.h"
22 #include "../common/containers.h"
23 #include "../common/test_step.h"
24 #include "../common/common_handlers.h"
33 /* Modify this to change the logging level of Meshlink */
34 #define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
36 static void test_case_mesh_channel_shutdown_01(void **state);
37 static bool test_steps_mesh_channel_shutdown_01(void);
38 static void test_case_mesh_channel_shutdown_02(void **state);
39 static bool test_steps_mesh_channel_shutdown_02(void);
40 static void test_case_mesh_channel_shutdown_03(void **state);
41 static bool test_steps_mesh_channel_shutdown_03(void);
43 static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len);
44 static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len);
46 /* State structure for meshlink_channel_shutdown Test Case #1 */
47 static black_box_state_t test_mesh_channel_shutdown_01_state = {
48 .test_case_name = "test_case_mesh_channel_shutdown_01",
51 /* State structure for meshlink_channel_shutdown Test Case #2 */
52 static black_box_state_t test_mesh_channel_shutdown_02_state = {
53 .test_case_name = "test_case_mesh_channel_shutdown_02",
56 /* State structure for meshlink_channel_shutdown Test Case #3 */
57 static black_box_state_t test_mesh_channel_shutdown_03_state = {
58 .test_case_name = "test_case_mesh_channel_shutdown_03",
61 static bool channel_acc;
63 static bool foo_responded;
64 static bool bar_responded;
66 /* mutex for the common variable */
67 static pthread_mutex_t accept_lock = PTHREAD_MUTEX_INITIALIZER;
68 static pthread_mutex_t poll_lock = PTHREAD_MUTEX_INITIALIZER;
69 static pthread_mutex_t bar_responded_lock = PTHREAD_MUTEX_INITIALIZER;
70 static pthread_mutex_t foo_responded_lock = PTHREAD_MUTEX_INITIALIZER;
72 static pthread_cond_t accept_cond = PTHREAD_COND_INITIALIZER;
73 static pthread_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
74 static pthread_cond_t foo_cond = PTHREAD_COND_INITIALIZER;
75 static pthread_cond_t bar_cond = PTHREAD_COND_INITIALIZER;
77 static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
83 meshlink_set_channel_receive_cb(mesh, channel, receive_cb);
84 channel->node->priv = channel;
85 pthread_mutex_lock(&accept_lock);
87 assert(!pthread_cond_broadcast(&accept_cond));
88 pthread_mutex_unlock(&accept_lock);
93 /* channel receive callback */
94 static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) {
98 if(!strcmp(mesh->name, "foo")) {
99 pthread_mutex_lock(& foo_responded_lock);
100 foo_responded = true;
101 assert(!pthread_cond_broadcast(&foo_cond));
102 pthread_mutex_unlock(& foo_responded_lock);
104 } else if(!strcmp(mesh->name, "bar")) {
105 pthread_mutex_lock(& bar_responded_lock);
106 bar_responded = true;
107 assert(!pthread_cond_broadcast(&bar_cond));
108 pthread_mutex_unlock(& bar_responded_lock);
110 assert(meshlink_channel_send(mesh, channel, "echo", 4) >= 0);
115 static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
118 meshlink_set_channel_poll_cb(mesh, channel, NULL);
119 pthread_mutex_lock(&poll_lock);
121 assert(!pthread_cond_broadcast(&poll_cond));
122 pthread_mutex_unlock(&poll_lock);
125 /* Execute meshlink_channel_shutdown Test Case # 1*/
126 static void test_case_mesh_channel_shutdown_01(void **state) {
127 execute_test(test_steps_mesh_channel_shutdown_01, state);
130 /* Test Steps for meshlink_channel_shutdown Test Case # 1 - Valid case
133 1. Open foo and bar instances and open a channel between them
134 2. Send data through the channel.
135 3. Shut down channel's read and send data
136 4. Shutdown channel's write and send data
139 Data is able to receive through channel before shutting down,
140 On shutting down read its should not able to receive data and when write
141 is shut down its should be able to send data through channel.
143 static bool test_steps_mesh_channel_shutdown_01(void) {
144 struct timespec timeout = {0};
145 meshlink_destroy("chan_shutdown_conf.1");
146 meshlink_destroy("chan_shutdown_conf.2");
147 // Open two new meshlink instance.
149 meshlink_handle_t *mesh1 = meshlink_open("chan_shutdown_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
150 assert(mesh1 != NULL);
152 meshlink_handle_t *mesh2 = meshlink_open("chan_shutdown_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
153 assert(mesh2 != NULL);
155 char *data = meshlink_export(mesh1);
157 assert(meshlink_import(mesh2, data));
159 data = meshlink_export(mesh2);
161 assert(meshlink_import(mesh1, data));
164 // Set the callbacks.
166 meshlink_set_channel_accept_cb(mesh2, accept_cb);
168 // Start both instances
170 assert(meshlink_start(mesh1));
171 assert(meshlink_start(mesh2));
174 // Open a channel from foo to bar.
176 meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
179 meshlink_channel_t *channel1 = meshlink_channel_open(mesh1, bar, 7, receive_cb, NULL, 0);
180 meshlink_set_channel_poll_cb(mesh1, channel1, poll_cb);
182 timeout.tv_sec = time(NULL) + 10;
183 pthread_mutex_lock(&poll_lock);
185 while(polled == false) {
186 assert(!pthread_cond_timedwait(&poll_cond, &poll_lock, &timeout));
189 pthread_mutex_unlock(&poll_lock);
191 timeout.tv_sec = time(NULL) + 10;
192 pthread_mutex_lock(&accept_lock);
194 while(channel_acc == false) {
195 assert(!pthread_cond_timedwait(&accept_cond, &accept_lock, &timeout));
198 pthread_mutex_unlock(&accept_lock);
200 // Sending to bar and testing the echo
202 assert(meshlink_channel_send(mesh1, channel1, "echo", 4) >= 0);
204 timeout.tv_sec = time(NULL) + 10;
205 pthread_mutex_lock(&foo_responded_lock);
207 while(foo_responded == false) {
208 assert(!pthread_cond_timedwait(&foo_cond, &foo_responded_lock, &timeout));
211 pthread_mutex_unlock(&foo_responded_lock);
212 assert(foo_responded);
214 // Shutting down channel read
216 meshlink_channel_shutdown(mesh1, channel1, SHUT_RD);
217 bar_responded = false;
218 foo_responded = false;
219 assert(meshlink_channel_send(mesh1, channel1, "echo", 4) >= 0);
221 timeout.tv_sec = time(NULL) + 10;
222 pthread_mutex_lock(&bar_responded_lock);
224 while(bar_responded == false) {
225 assert(!pthread_cond_timedwait(&bar_cond, &bar_responded_lock, &timeout));
228 pthread_mutex_unlock(&bar_responded_lock);
229 assert_int_equal(bar_responded, true);
231 assert_int_equal(foo_responded, false);
233 // Shutting down channel write
235 meshlink_channel_shutdown(mesh1, channel1, SHUT_WR);
237 ssize_t send_ret = meshlink_channel_send(mesh1, channel1, "echo", 4);
238 assert_int_equal(send_ret, -1);
242 meshlink_close(mesh2);
243 meshlink_close(mesh1);
244 meshlink_destroy("chan_shutdown_conf.1");
245 meshlink_destroy("chan_shutdown_conf.2");
250 /* Execute meshlink_channel_shutdown Test Case # 2*/
251 static void test_case_mesh_channel_shutdown_02(void **state) {
252 execute_test(test_steps_mesh_channel_shutdown_02, state);
255 /* Test Steps for meshlink_channel_shutdown Test Case # 2 - Invalid case
258 1. Open node instance and create a channel
259 2. Call meshlink_channel_shutdown API by passing NULL as mesh handle
262 meshlink_channel_shutdown API should report proper error handling
264 static bool test_steps_mesh_channel_shutdown_02(void) {
265 meshlink_destroy("channelshutdownconf.3");
266 meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
268 /* Create meshlink instance */
269 meshlink_handle_t *mesh_handle = meshlink_open("channelshutdownconf.3", "nut", "node_sim", 1);
270 assert(mesh_handle != NULL);
271 meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
272 meshlink_set_channel_accept_cb(mesh_handle, accept_cb);
274 assert(meshlink_start(mesh_handle));
276 meshlink_node_t *node = meshlink_get_self(mesh_handle);
277 assert(node != NULL);
279 meshlink_channel_t *channel = meshlink_channel_open(mesh_handle, node, 8000, NULL, NULL, 0);
281 meshlink_set_channel_poll_cb(mesh_handle, channel, poll_cb);
283 // Passing NULL as mesh handle and other arguments being valid
285 meshlink_channel_shutdown(NULL, channel, SHUT_WR);
286 assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
288 meshlink_close(mesh_handle);
289 meshlink_destroy("channelshutdownconf.3");
294 /* Execute meshlink_channel_shutdown Test Case # 3*/
295 static void test_case_mesh_channel_shutdown_03(void **state) {
296 execute_test(test_steps_mesh_channel_shutdown_03, state);
299 /* Test Steps for meshlink_channel_shutdown Test Case # 3
302 1. Open node instance
303 2. Call meshlink_channel_shutdown API by passing NULL as channel handle
306 meshlink_channel_shutdown API should report proper error handling
308 static bool test_steps_mesh_channel_shutdown_03(void) {
309 meshlink_destroy("channelshutdownconf.4");
310 meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
312 /* Create meshlink instance */
313 meshlink_handle_t *mesh_handle = meshlink_open("channelshutdownconf.4", "nut", "node_sim", 1);
314 assert(mesh_handle != NULL);
315 meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
316 meshlink_set_channel_accept_cb(mesh_handle, accept_cb);
318 assert(meshlink_start(mesh_handle));
320 // Passing NULL as mesh handle and other arguments being valid
322 meshlink_channel_shutdown(mesh_handle, NULL, SHUT_WR);
323 assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
325 meshlink_close(mesh_handle);
326 meshlink_destroy("channelshutdownconf.4");
332 int test_meshlink_channel_shutdown(void) {
333 const struct CMUnitTest blackbox_channel_shutdown_tests[] = {
334 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_shutdown_01, NULL, NULL,
335 (void *)&test_mesh_channel_shutdown_01_state),
336 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_shutdown_02, NULL, NULL,
337 (void *)&test_mesh_channel_shutdown_02_state),
338 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_shutdown_03, NULL, NULL,
339 (void *)&test_mesh_channel_shutdown_03_state)
341 total_tests += sizeof(blackbox_channel_shutdown_tests) / sizeof(blackbox_channel_shutdown_tests[0]);
343 return cmocka_run_group_tests(blackbox_channel_shutdown_tests, NULL, NULL);