2
** OSSP sa - Socket Abstraction
3
** Copyright (c) 2001-2004 Ralf S. Engelschall <rse@engelschall.com>
4
** Copyright (c) 2001-2004 The OSSP Project <http://www.ossp.org/>
5
** Copyright (c) 2001-2004 Cable & Wireless <http://www.cw.com/>
7
** This file is part of OSSP sa, a socket abstraction library which
8
** can be found at http://www.ossp.org/pkg/lib/sa/.
10
** Permission to use, copy, modify, and distribute this software for
11
** any purpose with or without fee is hereby granted, provided that
12
** the above copyright notice and this permission notice appear in all
15
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
16
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
19
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22
** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25
** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
** sa_test.c: socket abstraction library test suite
39
#include <sys/utsname.h>
42
#include <sys/types.h>
48
/* test: address import/export */
49
TS_TEST(test_saa_impexp)
62
{ "inet://0.0.0.0:0", SA_OK, "inet://0.0.0.0:0", NULL },
63
{ "inet://127.0.0.1:514", SA_OK, "inet://127.0.0.1:514", NULL },
64
{ "inet://localhost:syslog#udp", SA_OK, "inet://127.0.0.1:514", "inet://[::1]:514" },
65
{ "inet://localhost:smtp", SA_OK, "inet://127.0.0.1:25", "inet://[::1]:25" },
66
{ "unix:/tmp/socket", SA_OK, "unix:/tmp/socket", NULL },
68
{ "inet:", SA_ERR_ARG, NULL, NULL },
69
{ "inet://1.2.3.4.5:0", SA_ERR_ARG, NULL, NULL },
70
{ "inet://just-hostname", SA_ERR_ARG, NULL, NULL },
71
{ "unix:", SA_ERR_ARG, NULL, NULL }
74
ts_test_check(TS_CTX, "sa_addr_create");
75
if ((rv = sa_addr_create(&saa)) != SA_OK)
76
ts_test_fail(TS_CTX, "sa_addr_create -> %d[%s] (expected %d[%s])",
77
rv, sa_error(rv), SA_OK, sa_error(SA_OK));
78
for (i = 0; i < (int)(sizeof(table)/sizeof(table[0])); i++) {
79
ts_test_check(TS_CTX, "sa_addr_u2a(\"%s\")", table[i].in);
80
if ((rv = sa_addr_u2a(saa, table[i].in)) != table[i].rv)
81
ts_test_fail(TS_CTX, "sa_addr_a2u -> %d[%s] (expected %d[%s])",
82
rv, sa_error(rv), table[i].rv, sa_error(table[i].rv));
83
ts_test_check(TS_CTX, "sa_addr_a2u");
84
if ((rv = sa_addr_a2u(saa, &cp)) != SA_OK) {
85
ts_test_fail(TS_CTX, "sa_addr_u2a -> %d[%s] (expected %d[%s])",
86
rv, sa_error(rv), SA_OK, sa_error(SA_OK));
89
if (table[i].rv == SA_OK) {
90
if (table[i].out_alt != NULL) {
91
if (strcmp(cp, table[i].out) != 0 && strcmp(cp, table[i].out_alt) != 0)
92
ts_test_fail(TS_CTX, "sa_addr_a2u -> \"%s\" (expected \"%s\" or \"%s\")",
93
cp, table[i].out, table[i].out_alt);
96
if (strcmp(cp, table[i].out) != 0)
97
ts_test_fail(TS_CTX, "sa_addr_a2u -> \"%s\" (expected \"%s\")",
103
ts_test_check(TS_CTX, "sa_addr_destroy");
104
if ((rv = sa_addr_destroy(saa)) != SA_OK)
105
ts_test_fail(TS_CTX, "sa_addr_destroy -> %d[%s] (expected %d[%s])",
106
rv, sa_error(rv), SA_OK, sa_error(SA_OK));
109
/* test: address matching */
110
TS_TEST(test_saa_match)
122
{ "unix:/foo/bar", "unix:/foo/bar", -1, SA_OK },
123
{ "unix:/foo/bar", "unix:/foo/bar", 0, SA_OK },
124
{ "unix:/foo/bar", "unix:/foo", 4, SA_OK },
125
{ "unix:/foo/bar", "unix:/foo/quux", 4, SA_OK },
126
{ "unix:/foo/bar", "unix:/baz/quux", -1, SA_ERR_MTC },
127
{ "inet://0.0.0.0:0", "inet://0.0.0.0:0", 0, SA_OK },
128
{ "inet://127.0.0.1:514", "inet://127.0.0.1:514", -1, SA_OK },
129
{ "inet://127.0.0.1:514", "inet://0.0.0.0:0", 0, SA_OK },
130
{ "inet://127.0.0.1:514", "inet://12.34.56.78:9", 0, SA_OK },
131
{ "inet://127.0.0.1:514", "inet://12.34.56.78:9", -1, SA_ERR_MTC },
132
{ "inet://127.0.0.1:514", "inet://127.0.0.0:0", 24, SA_OK },
133
{ "inet://127.0.0.1:514", "inet://127.0.0.0:0", 32, SA_ERR_MTC },
134
{ "inet://141.1.23.20:25", "inet://141.1.23.40:25", 32, SA_ERR_MTC },
135
{ "inet://141.1.23.20:25", "inet://141.1.23.40:25", 24, SA_OK }
138
sa_addr_create(&saa1);
139
sa_addr_create(&saa2);
140
for (i = 0; i < (int)(sizeof(table)/sizeof(table[0])); i++) {
141
if ((rv = sa_addr_u2a(saa1, table[i].in)) != SA_OK)
143
if ((rv = sa_addr_u2a(saa2, table[i].acl)) != SA_OK)
145
ts_test_check(TS_CTX, "sa_addr_match(\"%s\", \"%s\", %d)",
146
table[i].in, table[i].acl, table[i].prefixlen);
147
if ((rv = sa_addr_match(saa1, saa2, table[i].prefixlen)) != table[i].rv)
148
ts_test_fail(TS_CTX, "sa_addr_match -> %d[%s] (expected %d[%s])",
149
rv, sa_error(rv), table[i].rv, sa_error(table[i].rv));
151
sa_addr_destroy(saa1);
152
sa_addr_destroy(saa2);
155
#define ex(proc, cmd) \
158
ts_test_check(TS_CTX, "%s: %s", #proc, #cmd); \
159
if ((__rv = (cmd)) != SA_OK) { \
160
if (__rv == SA_ERR_SYS) \
161
ts_test_fail(TS_CTX, "%s -> error: %s (rc=%d) (system: %s)", \
162
#cmd, sa_error(__rv), __rv, strerror(errno)); \
164
ts_test_fail(TS_CTX, "%s -> error: %s (rc=%d)", \
165
#cmd, sa_error(__rv), __rv); \
169
/* test: client/server stream communication */
170
TS_TEST(test_sa_stream)
183
#define MSG_TCP_SRV_WELCOME "Welcome client\n"
184
#define MSG_TCP_CLT_WELCOME "Welcome server\n"
185
#define MSG_TCP_SRV_GOODBYE "Goodbye client\n"
186
#define MSG_TCP_CLT_GOODBYE "Goodbye server\n"
188
if ((pid_srv = fork()) == 0) {
193
/* create server socket */
194
ex(SRV, sa_create(&sa_srv));
195
ex(SRV, sa_option(sa_srv, SA_OPTION_REUSEADDR, 1));
196
ex(SRV, sa_option(sa_srv, SA_OPTION_REUSEPORT, 1));
197
ex(SRV, sa_timeout(sa_srv, SA_TIMEOUT_ALL, 10, 0));
199
/* bind socket to local port */
200
ex(SRV, sa_addr_create(&saa_srv));
201
ex(SRV, sa_addr_u2a(saa_srv, "inet://127.0.0.1:12345#tcp"));
202
ex(SRV, sa_bind(sa_srv, saa_srv));
203
ex(SRV, sa_addr_destroy(saa_srv));
205
/* receive client connection */
206
ex(SRV, sa_listen(sa_srv, 10));
207
ex(SRV, sa_accept(sa_srv, &saa_cld, &sa_cld));
209
/* communicate with client */
210
ex(SRV, sa_writef(sa_cld, "%s", MSG_TCP_SRV_WELCOME));
211
ex(SRV, sa_readln(sa_cld, buf_srv, sizeof(buf_srv), &l));
212
if (strcmp(buf_srv, MSG_TCP_CLT_WELCOME) != 0)
213
ts_test_fail(TS_CTX, "server: got \"%s\", expected \"%s\"",
214
buf_srv, MSG_TCP_CLT_WELCOME);
215
ex(SRV, sa_writef(sa_cld, "%s", MSG_TCP_SRV_GOODBYE));
216
ex(SRV, sa_shutdown(sa_cld, "w"));
217
ex(SRV, sa_readln(sa_cld, buf_srv, sizeof(buf_srv), &l));
218
if (strcmp(buf_srv, MSG_TCP_CLT_GOODBYE) != 0)
219
ts_test_fail(TS_CTX, "server: got \"%s\", expected \"%s\"",
220
buf_srv, MSG_TCP_CLT_GOODBYE);
221
ex(SRV, sa_shutdown(sa_cld, "r"));
223
/* destroy client connection */
224
ex(SRV, sa_destroy(sa_cld));
225
ex(SRV, sa_addr_destroy(saa_cld));
227
/* destroy server socket and die */
228
ex(SRV, sa_destroy(sa_srv));
237
/* create client socket */
238
ex(CLT, sa_create(&sa_clt));
239
ex(CLT, sa_timeout(sa_clt, SA_TIMEOUT_ALL, 10, 0));
241
/* connect to server */
242
ex(CLT, sa_addr_create(&saa_clt));
243
ex(CLT, sa_addr_u2a(saa_clt, "inet://127.0.0.1:12345#tcp"));
244
ex(CLT, sa_connect(sa_clt, saa_clt));
245
ex(CLT, sa_addr_destroy(saa_clt));
247
/* communicate with server */
248
ex(CLT, sa_readln(sa_clt, buf_clt, sizeof(buf_clt), &l));
249
if (strcmp(buf_clt, MSG_TCP_SRV_WELCOME) != 0)
250
ts_test_fail(TS_CTX, "client: got \"%s\", expected \"%s\"",
251
buf_clt, MSG_TCP_SRV_WELCOME);
252
ex(CLT, sa_writef(sa_clt, "%s", MSG_TCP_CLT_WELCOME));
253
ex(CLT, sa_readln(sa_clt, buf_clt, sizeof(buf_clt), &l));
254
if (strcmp(buf_clt, MSG_TCP_SRV_GOODBYE) != 0)
255
ts_test_fail(TS_CTX, "client: got \"%s\", expected \"%s\"",
256
buf_clt, MSG_TCP_SRV_GOODBYE);
257
ex(CLT, sa_writef(sa_clt, "%s", MSG_TCP_CLT_GOODBYE));
258
ex(CLT, sa_shutdown(sa_clt, "rw"));
260
/* destroy server connection and wait for server to exit */
261
ex(CLT, sa_destroy(sa_clt));
262
waitpid(pid_srv, NULL, 0);
266
/* test: client/server datagram communication */
267
TS_TEST(test_sa_datagram)
278
#define MSG_UDP_CLT_REQUEST "Who are you?\n"
279
#define MSG_UDP_SRV_RESPONSE "I'm god\n"
281
if ((pid_srv = fork()) == 0) {
286
/* create server socket */
287
ex(SRV, sa_create(&sa_srv));
288
ex(SRV, sa_type(sa_srv, SA_TYPE_DATAGRAM));
289
ex(SRV, sa_option(sa_srv, SA_OPTION_REUSEADDR, 1));
290
ex(SRV, sa_option(sa_srv, SA_OPTION_REUSEPORT, 1));
291
ex(SRV, sa_timeout(sa_srv, SA_TIMEOUT_ALL, 10, 0));
293
/* bind socket to local port */
294
ex(SRV, sa_addr_create(&saa_srv));
295
ex(SRV, sa_addr_u2a(saa_srv, "inet://127.0.0.1:12345#udp"));
296
ex(SRV, sa_bind(sa_srv, saa_srv));
297
ex(SRV, sa_addr_destroy(saa_srv));
299
/* communicate with client */
300
ex(SRV, sa_recv(sa_srv, &saa_clt, buf_srv, sizeof(buf_srv), &l));
301
if (strncmp(buf_srv, MSG_UDP_CLT_REQUEST, l) != 0)
302
ts_test_fail(TS_CTX, "server: got \"%s\", expected \"%s\"",
303
buf_srv, MSG_UDP_CLT_REQUEST);
304
ex(SRV, sa_sendf(sa_srv, saa_clt, "%s", MSG_UDP_SRV_RESPONSE));
305
ex(SRV, sa_addr_destroy(saa_clt));
307
/* destroy server socket and die */
308
ex(SRV, sa_destroy(sa_srv));
317
/* create client socket */
318
ex(CLT, sa_create(&sa_clt));
319
ex(CLT, sa_type(sa_clt, SA_TYPE_DATAGRAM));
320
ex(CLT, sa_timeout(sa_clt, SA_TIMEOUT_ALL, 10, 0));
322
/* communicate with server */
323
ex(CLT, sa_addr_create(&saa_srv));
324
ex(CLT, sa_addr_u2a(saa_srv, "inet://127.0.0.1:12345#udp"));
325
ex(CLT, sa_sendf(sa_clt, saa_srv, "%s", MSG_UDP_CLT_REQUEST));
326
ex(CLT, sa_addr_destroy(saa_srv));
327
ex(CLT, sa_recv(sa_clt, &saa_srv, buf_clt, sizeof(buf_clt), &l));
328
if (strncmp(buf_clt, MSG_UDP_SRV_RESPONSE, l) != 0)
329
ts_test_fail(TS_CTX, "client: got \"%s\", expected \"%s\"",
330
buf_clt, MSG_UDP_SRV_RESPONSE);
331
ex(CLT, sa_addr_destroy(saa_srv));
333
/* destroy server connection and wait for server to exit */
334
ex(CLT, sa_destroy(sa_clt));
335
waitpid(pid_srv, NULL, 0);
339
/* test: exception handling */
348
ts_test_check(TS_CTX, "exception handling");
351
sa_addr_create(&saa);
352
sa_addr_u2a(saa, "inet:DUMMY");
353
sa_addr_destroy(saa);
356
if ((sa_rc_t)ex.ex_value != SA_ERR_ARG)
357
ts_test_fail(TS_CTX, "unexpected exception: %d\n", (sa_rc_t)ex.ex_value);
361
ts_test_fail(TS_CTX, "expected exception not caught\n");
365
int main(int argc, char *argv[])
370
ts = ts_suite_new("OSSP sa (Socket Abstraction)");
371
ts_suite_test(ts, test_saa_impexp, "socket address abstraction import/export");
372
ts_suite_test(ts, test_saa_match, "socket address abstraction matching");
373
ts_suite_test(ts, test_sa_stream, "socket abstraction stream communication");
374
ts_suite_test(ts, test_sa_datagram, "socket abstraction datagram communication");
376
ts_suite_test(ts, test_sa_ex, "exception handling");
378
n = ts_suite_run(ts);