]> git.meshlink.io Git - meshlink/blob - test/channels-aio-abort.c
Add a test case for meshlink_channel_abort() in combination with AIO.
[meshlink] / test / channels-aio-abort.c
1 #ifdef NDEBUG
2 #undef NDEBUG
3 #endif
4
5 #define _POSIX_C_SOURCE 200809L
6
7 #include <assert.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13
14 #include "meshlink.h"
15 #include "utils.h"
16
17 static const size_t size = 2000000; // size of data to transfer
18
19 struct aio_info {
20         char *data;
21         int callbacks;
22         size_t size;
23         struct timespec ts;
24         struct sync_flag flag;
25 };
26
27 static void aio_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len, void *priv) {
28         fprintf(stderr, "%s aio_cb %s %p %zu\n", mesh->name, channel->node->name, data, len);
29         (void)mesh;
30         (void)channel;
31         (void)data;
32         (void)len;
33
34         struct aio_info *info = priv;
35         clock_gettime(CLOCK_MONOTONIC, &info->ts);
36         info->callbacks++;
37         info->size += len;
38         set_sync_flag(&info->flag, true);
39         meshlink_channel_abort(mesh, channel);
40         free(info->data);
41 }
42
43 static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
44         fprintf(stderr, "%s accept %s\n", mesh->name, channel->node->name);
45         assert(port == 1);
46         assert(!data);
47         assert(!len);
48
49         struct aio_info *info = mesh->priv;
50
51         assert(meshlink_channel_aio_receive(mesh, channel, info->data, size / 2, aio_cb, info));
52
53         return true;
54 }
55
56 int main(void) {
57         meshlink_set_log_cb(NULL, MESHLINK_WARNING, log_cb);
58
59         struct aio_info in_info;
60         struct aio_info out_info;
61
62         memset(&in_info, 0, sizeof(in_info));
63         memset(&out_info, 0, sizeof(out_info));
64
65         init_sync_flag(&in_info.flag);
66         init_sync_flag(&out_info.flag);
67
68         in_info.data = calloc(1, size / 2);
69         assert(in_info.data);
70         out_info.data = calloc(1, size);
71         assert(out_info.data);
72
73         // Open two new meshlink instance.
74
75         meshlink_handle_t *mesh_a, *mesh_b;
76         open_meshlink_pair(&mesh_a, &mesh_b, "channels_aio_abort");
77
78         // Set the callbacks.
79
80         mesh_b->priv = &in_info;
81         meshlink_set_channel_accept_cb(mesh_b, accept_cb);
82
83         // Start both instances
84
85         start_meshlink_pair(mesh_a, mesh_b);
86
87         // Open channel from a to b.
88
89         meshlink_node_t *b = meshlink_get_node(mesh_a, "b");
90         assert(b);
91         meshlink_channel_t *channel = meshlink_channel_open(mesh_a, b, 1, NULL, NULL, 0);
92         assert(channel);
93
94         // Send data, receiver aborts halfway
95
96         assert(meshlink_channel_aio_send(mesh_a, channel, out_info.data, size, aio_cb, &out_info));
97
98         // Wait for everyone to finish.
99
100         assert(wait_sync_flag(&out_info.flag, 10));
101         assert(wait_sync_flag(&in_info.flag, 10));
102
103         // Open a new data, now sender aborts halfway
104
105         init_sync_flag(&in_info.flag);
106         init_sync_flag(&out_info.flag);
107
108         in_info.data = calloc(1, size / 2);
109         assert(in_info.data);
110         out_info.data = calloc(1, size / 4);
111         assert(out_info.data);
112
113         channel = meshlink_channel_open(mesh_a, b, 1, NULL, NULL, 0);
114         assert(channel);
115         assert(meshlink_channel_aio_send(mesh_a, channel, out_info.data, size / 4, aio_cb, &out_info));
116
117         // Wait for everyone to finish.
118
119         assert(wait_sync_flag(&out_info.flag, 10));
120         assert(wait_sync_flag(&in_info.flag, 10));
121
122         // Clean up.
123
124         close_meshlink_pair(mesh_a, mesh_b);
125 }