unit-tests: Add test suite for streams and services
[strongswan.git] / src / libstrongswan / tests / suites / test_stream.c
1 /*
2 * Copyright (C) 2013 Martin Willi
3 * Copyright (C) 2013 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "test_suite.h"
17
18 #include <unistd.h>
19
20 static char* services[] = {
21 "unix:///tmp/strongswan-test-service.sck",
22 "tcp://127.0.0.1:7766",
23 "tcp://[::1]:7766",
24 };
25
26 static char msg[] = "testmessage";
27 static int msglen = 12;
28
29 static bool servicing(void *data, stream_t *stream)
30 {
31 char buf[64];
32 ssize_t len, total;
33
34 ck_assert(streq((char*)data, "test"));
35
36 for (total = 0; total < msglen;)
37 {
38 len = stream->read(stream, buf, sizeof(buf), TRUE);
39 ck_assert(len > 0);
40 total += len;
41 }
42 for (total = 0; total < msglen;)
43 {
44 len = stream->write(stream, buf, len, TRUE);
45 ck_assert(len > 0);
46 total += len;
47 }
48
49 return FALSE;
50 }
51
52 START_TEST(test_sync)
53 {
54 char buf[64];
55 stream_service_t *service;
56 stream_t *stream;
57 ssize_t len, total;
58
59 lib->processor->set_threads(lib->processor, 8);
60
61 service = lib->streams->create_service(lib->streams, services[_i], 1);
62 ck_assert(service != NULL);
63 service->on_accept(service, servicing, "test", JOB_PRIO_HIGH, 1);
64
65 stream = lib->streams->connect(lib->streams, services[_i]);
66 ck_assert(stream != NULL);
67 for (total = 0; total < msglen;)
68 {
69 len = stream->write(stream, msg, msglen, TRUE);
70 ck_assert(len > 0);
71 total += len;
72 }
73 for (total = 0; total < msglen;)
74 {
75 len = stream->read(stream, buf, sizeof(buf), TRUE);
76 ck_assert(len > 0);
77 total += len;
78 }
79 ck_assert(streq(buf, msg));
80 stream->destroy(stream);
81
82 service->destroy(service);
83 }
84 END_TEST
85
86 static bool on_write(void *data, stream_t *stream)
87 {
88 ssize_t len, total;
89
90 ck_assert(streq((char*)data, "test-write"));
91 for (total = 0; total < msglen;)
92 {
93 len = stream->write(stream, msg, msglen, TRUE);
94 ck_assert(len > 0);
95 total += len;
96 }
97 return FALSE;
98 }
99
100 static bool read_done = FALSE;
101
102 static bool on_read(void *data, stream_t *stream)
103 {
104 ssize_t len, total;
105 char buf[64];
106
107 ck_assert(streq((char*)data, "test-read"));
108 for (total = 0; total < msglen;)
109 {
110 len = stream->read(stream, buf, sizeof(buf), TRUE);
111 ck_assert(len > 0);
112 total += len;
113 }
114 ck_assert(streq(buf, msg));
115 read_done = TRUE;
116 return FALSE;
117 }
118
119 START_TEST(test_async)
120 {
121 stream_service_t *service;
122 stream_t *stream;
123
124
125 lib->processor->set_threads(lib->processor, 8);
126
127 service = lib->streams->create_service(lib->streams, services[_i], 1);
128 ck_assert(service != NULL);
129 service->on_accept(service, servicing, "test", JOB_PRIO_HIGH, 0);
130
131 stream = lib->streams->connect(lib->streams, services[_i]);
132 ck_assert(stream != NULL);
133 read_done = FALSE;
134 stream->on_write(stream, (stream_cb_t)on_write, "test-write");
135 stream->on_read(stream, (stream_cb_t)on_read, "test-read");
136
137 while (!read_done)
138 {
139 usleep(1000);
140 }
141 stream->destroy(stream);
142
143 service->destroy(service);
144 }
145 END_TEST
146
147 static bool all(void *data, stream_t *stream)
148 {
149 char buf[64], *pos;
150 ssize_t len;
151 int i;
152
153 pos = buf;
154 for (i = 0; i < msglen; i++)
155 {
156 len = stream->read(stream, pos, 1, TRUE);
157 ck_assert_int_eq(len, 1);
158 pos += len;
159 }
160 pos = buf;
161 for (i = 0; i < msglen; i++)
162 {
163 len = stream->write(stream, pos, 1, TRUE);
164 ck_assert_int_eq(len, 1);
165 pos += len;
166 }
167
168 return FALSE;
169 }
170
171 START_TEST(test_all)
172 {
173 char buf[64];
174 stream_service_t *service;
175 stream_t *stream;
176
177 lib->processor->set_threads(lib->processor, 8);
178
179 service = lib->streams->create_service(lib->streams, services[_i], 1);
180 ck_assert(service != NULL);
181 service->on_accept(service, all, NULL, JOB_PRIO_HIGH, 1);
182
183 stream = lib->streams->connect(lib->streams, services[_i]);
184 ck_assert(stream != NULL);
185 ck_assert(stream->write_all(stream, msg, msglen));
186 ck_assert(stream->read_all(stream, buf, msglen));
187 ck_assert(streq(buf, msg));
188 stream->destroy(stream);
189
190 service->destroy(service);
191 }
192 END_TEST
193
194 static bool concurrency(void *data, stream_t *stream)
195 {
196 static refcount_t refs = 0;
197 u_int current;
198 ssize_t len;
199
200 current = ref_get(&refs);
201 ck_assert(current <= 3);
202 len = stream->write(stream, "x", 1, TRUE);
203 ck_assert_int_eq(len, 1);
204 usleep(1000);
205 ignore_result(ref_put(&refs));
206
207 return FALSE;
208 }
209
210 START_TEST(test_concurrency)
211 {
212 stream_service_t *service;
213 stream_t *streams[10];
214 ssize_t len;
215 char x;
216 int i;
217
218 lib->processor->set_threads(lib->processor, 8);
219
220 service = lib->streams->create_service(lib->streams, services[_i], 10);
221 ck_assert(service != NULL);
222 service->on_accept(service, concurrency, NULL, JOB_PRIO_HIGH, 3);
223
224 for (i = 0; i < countof(streams); i++)
225 {
226 streams[i] = lib->streams->connect(lib->streams, services[_i]);
227 ck_assert(streams[i] != NULL);
228 }
229 for (i = 0; i < countof(streams); i++)
230 {
231 len = streams[i]->read(streams[i], &x, 1, TRUE);
232 ck_assert_int_eq(len, 1);
233 ck_assert_int_eq(x, 'x');
234 }
235 for (i = 0; i < countof(streams); i++)
236 {
237 streams[i]->destroy(streams[i]);
238 }
239 service->destroy(service);
240 }
241 END_TEST
242
243 Suite *stream_suite_create()
244 {
245 Suite *s;
246 TCase *tc;
247
248 s = suite_create("stream");
249
250 tc = tcase_create("sync");
251 tcase_add_loop_test(tc, test_sync, 0, countof(services));
252 suite_add_tcase(s, tc);
253
254 tc = tcase_create("async");
255 tcase_add_loop_test(tc, test_async, 0, countof(services));
256 suite_add_tcase(s, tc);
257
258 tc = tcase_create("all");
259 tcase_add_loop_test(tc, test_all, 0, countof(services));
260 suite_add_tcase(s, tc);
261
262 tc = tcase_create("concurrency");
263 tcase_add_loop_test(tc, test_concurrency, 0, countof(services));
264 suite_add_tcase(s, tc);
265
266 return s;
267 }