1/*
2 * utils module tests
3 * Copyright (c) 2014-2015, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
12#include "common/ieee802_11_defs.h"
13#include "utils/bitfield.h"
14#include "utils/ext_password.h"
15#include "utils/trace.h"
16#include "utils/base64.h"
17#include "utils/ip_addr.h"
18#include "utils/eloop.h"
19
20
21struct printf_test_data {
22	u8 *data;
23	size_t len;
24	char *encoded;
25};
26
27static const struct printf_test_data printf_tests[] = {
28	{ (u8 *) "abcde", 5, "abcde" },
29	{ (u8 *) "a\0b\nc\ed\re\tf\"\\", 13, "a\\0b\\nc\\ed\\re\\tf\\\"\\\\" },
30	{ (u8 *) "\x00\x31\x00\x32\x00\x39", 6, "\\x001\\0002\\09" },
31	{ (u8 *) "\n\n\n", 3, "\n\12\x0a" },
32	{ (u8 *) "\303\245\303\244\303\266\303\205\303\204\303\226", 12,
33	  "\\xc3\\xa5\xc3\\xa4\\xc3\\xb6\\xc3\\x85\\xc3\\x84\\xc3\\x96" },
34	{ (u8 *) "\303\245\303\244\303\266\303\205\303\204\303\226", 12,
35	  "\\303\\245\\303\\244\\303\\266\\303\\205\\303\\204\\303\\226" },
36	{ (u8 *) "\xe5\xe4\xf6\xc5\xc4\xd6", 6,
37	  "\\xe5\\xe4\\xf6\\xc5\\xc4\\xd6" },
38	{ NULL, 0, NULL }
39};
40
41
42static int printf_encode_decode_tests(void)
43{
44	int i;
45	size_t binlen;
46	char buf[100];
47	u8 bin[100];
48	int errors = 0;
49	int array[10];
50
51	wpa_printf(MSG_INFO, "printf encode/decode tests");
52
53	for (i = 0; printf_tests[i].data; i++) {
54		const struct printf_test_data *test = &printf_tests[i];
55		printf_encode(buf, sizeof(buf), test->data, test->len);
56		wpa_printf(MSG_INFO, "%d: -> \"%s\"", i, buf);
57
58		binlen = printf_decode(bin, sizeof(bin), buf);
59		if (binlen != test->len ||
60		    os_memcmp(bin, test->data, binlen) != 0) {
61			wpa_hexdump(MSG_ERROR, "Error in decoding#1",
62				    bin, binlen);
63			errors++;
64		}
65
66		binlen = printf_decode(bin, sizeof(bin), test->encoded);
67		if (binlen != test->len ||
68		    os_memcmp(bin, test->data, binlen) != 0) {
69			wpa_hexdump(MSG_ERROR, "Error in decoding#2",
70				    bin, binlen);
71			errors++;
72		}
73	}
74
75	buf[5] = 'A';
76	printf_encode(buf, 5, (const u8 *) "abcde", 5);
77	if (buf[5] != 'A') {
78		wpa_printf(MSG_ERROR, "Error in bounds checking#1");
79		errors++;
80	}
81
82	for (i = 5; i < 10; i++) {
83		buf[i] = 'A';
84		printf_encode(buf, i, (const u8 *) "\xdd\xdd\xdd\xdd\xdd", 5);
85		if (buf[i] != 'A') {
86			wpa_printf(MSG_ERROR, "Error in bounds checking#2(%d)",
87				   i);
88			errors++;
89		}
90	}
91
92	if (printf_decode(bin, 3, "abcde") != 2)
93		errors++;
94
95	if (printf_decode(bin, 3, "\\xa") != 1 || bin[0] != 10)
96		errors++;
97
98	if (printf_decode(bin, 3, "\\xq") != 1 || bin[0] != 'q')
99		errors++;
100
101	if (printf_decode(bin, 3, "\\a") != 1 || bin[0] != 'a')
102		errors++;
103
104	array[0] = 10;
105	array[1] = 10;
106	array[2] = 5;
107	array[3] = 10;
108	array[4] = 5;
109	array[5] = 0;
110	if (int_array_len(array) != 5)
111		errors++;
112	int_array_sort_unique(array);
113	if (int_array_len(array) != 2)
114		errors++;
115
116	if (errors) {
117		wpa_printf(MSG_ERROR, "%d printf test(s) failed", errors);
118		return -1;
119	}
120
121	return 0;
122}
123
124
125static int bitfield_tests(void)
126{
127	struct bitfield *bf;
128	int i;
129	int errors = 0;
130
131	wpa_printf(MSG_INFO, "bitfield tests");
132
133	bf = bitfield_alloc(123);
134	if (bf == NULL)
135		return -1;
136
137	for (i = 0; i < 123; i++) {
138		if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1))
139			errors++;
140		if (i > 0 && bitfield_is_set(bf, i - 1))
141			errors++;
142		bitfield_set(bf, i);
143		if (!bitfield_is_set(bf, i))
144			errors++;
145		bitfield_clear(bf, i);
146		if (bitfield_is_set(bf, i))
147			errors++;
148	}
149
150	for (i = 123; i < 200; i++) {
151		if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1))
152			errors++;
153		if (i > 0 && bitfield_is_set(bf, i - 1))
154			errors++;
155		bitfield_set(bf, i);
156		if (bitfield_is_set(bf, i))
157			errors++;
158		bitfield_clear(bf, i);
159		if (bitfield_is_set(bf, i))
160			errors++;
161	}
162
163	for (i = 0; i < 123; i++) {
164		if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1))
165			errors++;
166		bitfield_set(bf, i);
167		if (!bitfield_is_set(bf, i))
168			errors++;
169	}
170
171	for (i = 0; i < 123; i++) {
172		if (!bitfield_is_set(bf, i))
173			errors++;
174		bitfield_clear(bf, i);
175		if (bitfield_is_set(bf, i))
176			errors++;
177	}
178
179	for (i = 0; i < 123; i++) {
180		if (bitfield_get_first_zero(bf) != i)
181			errors++;
182		bitfield_set(bf, i);
183	}
184	if (bitfield_get_first_zero(bf) != -1)
185		errors++;
186	for (i = 0; i < 123; i++) {
187		if (!bitfield_is_set(bf, i))
188			errors++;
189		bitfield_clear(bf, i);
190		if (bitfield_get_first_zero(bf) != i)
191			errors++;
192		bitfield_set(bf, i);
193	}
194	if (bitfield_get_first_zero(bf) != -1)
195		errors++;
196
197	bitfield_free(bf);
198
199	bf = bitfield_alloc(8);
200	if (bf == NULL)
201		return -1;
202	if (bitfield_get_first_zero(bf) != 0)
203		errors++;
204	for (i = 0; i < 8; i++)
205		bitfield_set(bf, i);
206	if (bitfield_get_first_zero(bf) != -1)
207		errors++;
208	bitfield_free(bf);
209
210	if (errors) {
211		wpa_printf(MSG_ERROR, "%d bitfield test(s) failed", errors);
212		return -1;
213	}
214
215	return 0;
216}
217
218
219static int int_array_tests(void)
220{
221	int test1[] = { 1, 2, 3, 4, 5, 6, 0 };
222	int test2[] = { 1, -1, 0 };
223	int test3[] = { 1, 1, 1, -1, 2, 3, 4, 1, 2, 0 };
224	int test3_res[] = { -1, 1, 2, 3, 4, 0 };
225	int errors = 0;
226	int len;
227
228	wpa_printf(MSG_INFO, "int_array tests");
229
230	if (int_array_len(test1) != 6 ||
231	    int_array_len(test2) != 2)
232		errors++;
233
234	int_array_sort_unique(test3);
235	len = int_array_len(test3_res);
236	if (int_array_len(test3) != len)
237		errors++;
238	else if (os_memcmp(test3, test3_res, len * sizeof(int)) != 0)
239		errors++;
240
241	if (errors) {
242		wpa_printf(MSG_ERROR, "%d int_array test(s) failed", errors);
243		return -1;
244	}
245
246	return 0;
247}
248
249
250static int ext_password_tests(void)
251{
252	struct ext_password_data *data;
253	int ret = 0;
254	struct wpabuf *pw;
255
256	wpa_printf(MSG_INFO, "ext_password tests");
257
258	data = ext_password_init("unknown", "foo");
259	if (data != NULL)
260		return -1;
261
262	data = ext_password_init("test", NULL);
263	if (data == NULL)
264		return -1;
265	pw = ext_password_get(data, "foo");
266	if (pw != NULL)
267		ret = -1;
268	ext_password_free(pw);
269
270	ext_password_deinit(data);
271
272	pw = ext_password_get(NULL, "foo");
273	if (pw != NULL)
274		ret = -1;
275	ext_password_free(pw);
276
277	return ret;
278}
279
280
281static int trace_tests(void)
282{
283	wpa_printf(MSG_INFO, "trace tests");
284
285	wpa_trace_show("test backtrace");
286	wpa_trace_dump_funcname("test funcname", trace_tests);
287
288	return 0;
289}
290
291
292static int base64_tests(void)
293{
294	int errors = 0;
295	unsigned char *res;
296	size_t res_len;
297
298	wpa_printf(MSG_INFO, "base64 tests");
299
300	res = base64_encode((const unsigned char *) "", ~0, &res_len);
301	if (res) {
302		errors++;
303		os_free(res);
304	}
305
306	res = base64_encode((const unsigned char *) "=", 1, &res_len);
307	if (!res || res_len != 5 || res[0] != 'P' || res[1] != 'Q' ||
308	    res[2] != '=' || res[3] != '=' || res[4] != '\n')
309		errors++;
310	os_free(res);
311
312	res = base64_encode((const unsigned char *) "=", 1, NULL);
313	if (!res || res[0] != 'P' || res[1] != 'Q' ||
314	    res[2] != '=' || res[3] != '=' || res[4] != '\n')
315		errors++;
316	os_free(res);
317
318	res = base64_decode((const unsigned char *) "", 0, &res_len);
319	if (res) {
320		errors++;
321		os_free(res);
322	}
323
324	res = base64_decode((const unsigned char *) "a", 1, &res_len);
325	if (res) {
326		errors++;
327		os_free(res);
328	}
329
330	res = base64_decode((const unsigned char *) "====", 4, &res_len);
331	if (res) {
332		errors++;
333		os_free(res);
334	}
335
336	res = base64_decode((const unsigned char *) "PQ==", 4, &res_len);
337	if (!res || res_len != 1 || res[0] != '=')
338		errors++;
339	os_free(res);
340
341	res = base64_decode((const unsigned char *) "P.Q-=!=*", 8, &res_len);
342	if (!res || res_len != 1 || res[0] != '=')
343		errors++;
344	os_free(res);
345
346	if (errors) {
347		wpa_printf(MSG_ERROR, "%d base64 test(s) failed", errors);
348		return -1;
349	}
350
351	return 0;
352}
353
354
355static int common_tests(void)
356{
357	char buf[3], longbuf[100];
358	u8 addr[ETH_ALEN] = { 1, 2, 3, 4, 5, 6 };
359	u8 bin[3];
360	int errors = 0;
361	struct wpa_freq_range_list ranges;
362	size_t len;
363	const char *txt;
364	u8 ssid[255];
365
366	wpa_printf(MSG_INFO, "common tests");
367
368	if (hwaddr_mask_txt(buf, 3, addr, addr) != -1)
369		errors++;
370
371	if (wpa_scnprintf(buf, 0, "hello") != 0 ||
372	    wpa_scnprintf(buf, 3, "hello") != 2)
373		errors++;
374
375	if (wpa_snprintf_hex(buf, 0, addr, ETH_ALEN) != 0 ||
376	    wpa_snprintf_hex(buf, 3, addr, ETH_ALEN) != 2)
377		errors++;
378
379	if (merge_byte_arrays(bin, 3, addr, ETH_ALEN, NULL, 0) != 3 ||
380	    merge_byte_arrays(bin, 3, NULL, 0, addr, ETH_ALEN) != 3)
381		errors++;
382
383	if (dup_binstr(NULL, 0) != NULL)
384		errors++;
385
386	if (freq_range_list_includes(NULL, 0) != 0)
387		errors++;
388
389	os_memset(&ranges, 0, sizeof(ranges));
390	if (freq_range_list_parse(&ranges, "") != 0 ||
391	    freq_range_list_includes(&ranges, 0) != 0 ||
392	    freq_range_list_str(&ranges) != NULL)
393		errors++;
394
395	if (utf8_unescape(NULL, 0, buf, sizeof(buf)) != 0 ||
396	    utf8_unescape("a", 1, NULL, 0) != 0 ||
397	    utf8_unescape("a\\", 2, buf, sizeof(buf)) != 0 ||
398	    utf8_unescape("abcde", 5, buf, sizeof(buf)) != 0 ||
399	    utf8_unescape("abc", 3, buf, 3) != 3)
400		errors++;
401
402	if (utf8_unescape("a", 0, buf, sizeof(buf)) != 1 || buf[0] != 'a')
403		errors++;
404
405	if (utf8_unescape("\\b", 2, buf, sizeof(buf)) != 1 || buf[0] != 'b')
406		errors++;
407
408	if (utf8_escape(NULL, 0, buf, sizeof(buf)) != 0 ||
409	    utf8_escape("a", 1, NULL, 0) != 0 ||
410	    utf8_escape("abcde", 5, buf, sizeof(buf)) != 0 ||
411	    utf8_escape("a\\bcde", 6, buf, sizeof(buf)) != 0 ||
412	    utf8_escape("ab\\cde", 6, buf, sizeof(buf)) != 0 ||
413	    utf8_escape("abc\\de", 6, buf, sizeof(buf)) != 0 ||
414	    utf8_escape("abc", 3, buf, 3) != 3)
415		errors++;
416
417	if (utf8_escape("a", 0, buf, sizeof(buf)) != 1 || buf[0] != 'a')
418		errors++;
419
420	os_memset(ssid, 0, sizeof(ssid));
421	txt = wpa_ssid_txt(ssid, sizeof(ssid));
422	len = os_strlen(txt);
423	/* Verify that SSID_MAX_LEN * 4 buffer limit is enforced. */
424	if (len != SSID_MAX_LEN * 4) {
425		wpa_printf(MSG_ERROR,
426			   "Unexpected wpa_ssid_txt() result with too long SSID");
427		errors++;
428	}
429
430	if (wpa_snprintf_hex_sep(longbuf, 0, addr, ETH_ALEN, '-') != 0 ||
431	    wpa_snprintf_hex_sep(longbuf, 5, addr, ETH_ALEN, '-') != 3 ||
432	    os_strcmp(longbuf, "01-0") != 0)
433		errors++;
434
435	if (errors) {
436		wpa_printf(MSG_ERROR, "%d common test(s) failed", errors);
437		return -1;
438	}
439
440	return 0;
441}
442
443
444static int os_tests(void)
445{
446	int errors = 0;
447	void *ptr;
448	os_time_t t;
449
450	wpa_printf(MSG_INFO, "os tests");
451
452	ptr = os_calloc((size_t) -1, (size_t) -1);
453	if (ptr) {
454		errors++;
455		os_free(ptr);
456	}
457	ptr = os_calloc((size_t) 2, (size_t) -1);
458	if (ptr) {
459		errors++;
460		os_free(ptr);
461	}
462	ptr = os_calloc((size_t) -1, (size_t) 2);
463	if (ptr) {
464		errors++;
465		os_free(ptr);
466	}
467
468	ptr = os_realloc_array(NULL, (size_t) -1, (size_t) -1);
469	if (ptr) {
470		errors++;
471		os_free(ptr);
472	}
473
474	os_sleep(1, 1);
475
476	if (os_mktime(1969, 1, 1, 1, 1, 1, &t) == 0 ||
477	    os_mktime(1971, 0, 1, 1, 1, 1, &t) == 0 ||
478	    os_mktime(1971, 13, 1, 1, 1, 1, &t) == 0 ||
479	    os_mktime(1971, 1, 0, 1, 1, 1, &t) == 0 ||
480	    os_mktime(1971, 1, 32, 1, 1, 1, &t) == 0 ||
481	    os_mktime(1971, 1, 1, -1, 1, 1, &t) == 0 ||
482	    os_mktime(1971, 1, 1, 24, 1, 1, &t) == 0 ||
483	    os_mktime(1971, 1, 1, 1, -1, 1, &t) == 0 ||
484	    os_mktime(1971, 1, 1, 1, 60, 1, &t) == 0 ||
485	    os_mktime(1971, 1, 1, 1, 1, -1, &t) == 0 ||
486	    os_mktime(1971, 1, 1, 1, 1, 61, &t) == 0 ||
487	    os_mktime(1971, 1, 1, 1, 1, 1, &t) != 0 ||
488	    os_mktime(2020, 1, 2, 3, 4, 5, &t) != 0 ||
489	    os_mktime(2015, 12, 31, 23, 59, 59, &t) != 0)
490		errors++;
491
492	if (os_setenv("hwsim_test_env", "test value", 0) != 0 ||
493	    os_setenv("hwsim_test_env", "test value 2", 1) != 0 ||
494	    os_unsetenv("hwsim_test_env") != 0)
495		errors++;
496
497	if (os_file_exists("/this-file-does-not-exists-hwsim") != 0)
498		errors++;
499
500	if (errors) {
501		wpa_printf(MSG_ERROR, "%d os test(s) failed", errors);
502		return -1;
503	}
504
505	return 0;
506}
507
508
509static int wpabuf_tests(void)
510{
511	int errors = 0;
512	void *ptr;
513	struct wpabuf *buf;
514
515	wpa_printf(MSG_INFO, "wpabuf tests");
516
517	ptr = os_malloc(100);
518	if (ptr) {
519		buf = wpabuf_alloc_ext_data(ptr, 100);
520		if (buf) {
521			if (wpabuf_resize(&buf, 100) < 0)
522				errors++;
523			else
524				wpabuf_put(buf, 100);
525			wpabuf_free(buf);
526		} else {
527			errors++;
528			os_free(ptr);
529		}
530	} else {
531		errors++;
532	}
533
534	buf = wpabuf_alloc(100);
535	if (buf) {
536		struct wpabuf *buf2;
537
538		wpabuf_put(buf, 100);
539		if (wpabuf_resize(&buf, 100) < 0)
540			errors++;
541		else
542			wpabuf_put(buf, 100);
543		buf2 = wpabuf_concat(buf, NULL);
544		if (buf2 != buf)
545			errors++;
546		wpabuf_free(buf2);
547	} else {
548		errors++;
549	}
550
551	buf = NULL;
552	buf = wpabuf_zeropad(buf, 10);
553	if (buf != NULL)
554		errors++;
555
556	if (errors) {
557		wpa_printf(MSG_ERROR, "%d wpabuf test(s) failed", errors);
558		return -1;
559	}
560
561	return 0;
562}
563
564
565static int ip_addr_tests(void)
566{
567	int errors = 0;
568	struct hostapd_ip_addr addr;
569	char buf[100];
570
571	wpa_printf(MSG_INFO, "ip_addr tests");
572
573	if (hostapd_parse_ip_addr("1.2.3.4", &addr) != 0 ||
574	    addr.af != AF_INET ||
575	    hostapd_ip_txt(NULL, buf, sizeof(buf)) != NULL ||
576	    hostapd_ip_txt(&addr, buf, 1) != buf || buf[0] != '\0' ||
577	    hostapd_ip_txt(&addr, buf, 0) != NULL ||
578	    hostapd_ip_txt(&addr, buf, sizeof(buf)) != buf)
579		errors++;
580
581	if (hostapd_parse_ip_addr("::", &addr) != 0 ||
582	    addr.af != AF_INET6 ||
583	    hostapd_ip_txt(&addr, buf, 1) != buf || buf[0] != '\0' ||
584	    hostapd_ip_txt(&addr, buf, sizeof(buf)) != buf)
585		errors++;
586
587	if (errors) {
588		wpa_printf(MSG_ERROR, "%d ip_addr test(s) failed", errors);
589		return -1;
590	}
591
592	return 0;
593}
594
595
596struct test_eloop {
597	unsigned int magic;
598	int close_in_timeout;
599	int pipefd1[2];
600	int pipefd2[2];
601};
602
603
604static void eloop_tests_start(int close_in_timeout);
605
606
607static void eloop_test_read_2(int sock, void *eloop_ctx, void *sock_ctx)
608{
609	struct test_eloop *t = eloop_ctx;
610	ssize_t res;
611	char buf[10];
612
613	wpa_printf(MSG_INFO, "%s: sock=%d", __func__, sock);
614
615	if (t->magic != 0x12345678) {
616		wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
617			   __func__, t->magic);
618	}
619
620	if (t->pipefd2[0] != sock) {
621		wpa_printf(MSG_INFO, "%s: unexpected sock %d != %d",
622			   __func__, sock, t->pipefd2[0]);
623	}
624
625	res = read(sock, buf, sizeof(buf));
626	wpa_printf(MSG_INFO, "%s: sock=%d --> res=%d",
627		   __func__, sock, (int) res);
628}
629
630
631static void eloop_test_read_2_wrong(int sock, void *eloop_ctx, void *sock_ctx)
632{
633	struct test_eloop *t = eloop_ctx;
634
635	wpa_printf(MSG_INFO, "%s: sock=%d", __func__, sock);
636
637	if (t->magic != 0x12345678) {
638		wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
639			   __func__, t->magic);
640	}
641
642	if (t->pipefd2[0] != sock) {
643		wpa_printf(MSG_INFO, "%s: unexpected sock %d != %d",
644			   __func__, sock, t->pipefd2[0]);
645	}
646
647	/*
648	 * This is expected to block due to the original socket with data having
649	 * been closed and no new data having been written to the new socket
650	 * with the same fd. To avoid blocking the process during test, skip the
651	 * read here.
652	 */
653	wpa_printf(MSG_ERROR, "%s: FAIL - should not have called this function",
654		   __func__);
655}
656
657
658static void reopen_pipefd2(struct test_eloop *t)
659{
660	if (t->pipefd2[0] < 0) {
661		wpa_printf(MSG_INFO, "pipefd2 had been closed");
662	} else {
663		int res;
664
665		wpa_printf(MSG_INFO, "close pipefd2");
666		eloop_unregister_read_sock(t->pipefd2[0]);
667		close(t->pipefd2[0]);
668		t->pipefd2[0] = -1;
669		close(t->pipefd2[1]);
670		t->pipefd2[1] = -1;
671
672		res = pipe(t->pipefd2);
673		if (res < 0) {
674			wpa_printf(MSG_INFO, "pipe: %s", strerror(errno));
675			t->pipefd2[0] = -1;
676			t->pipefd2[1] = -1;
677			return;
678		}
679
680		wpa_printf(MSG_INFO,
681			   "re-register pipefd2 with new sockets %d,%d",
682			   t->pipefd2[0], t->pipefd2[1]);
683		eloop_register_read_sock(t->pipefd2[0], eloop_test_read_2_wrong,
684					 t, NULL);
685	}
686}
687
688
689static void eloop_test_read_1(int sock, void *eloop_ctx, void *sock_ctx)
690{
691	struct test_eloop *t = eloop_ctx;
692	ssize_t res;
693	char buf[10];
694
695	wpa_printf(MSG_INFO, "%s: sock=%d", __func__, sock);
696
697	if (t->magic != 0x12345678) {
698		wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
699			   __func__, t->magic);
700	}
701
702	if (t->pipefd1[0] != sock) {
703		wpa_printf(MSG_INFO, "%s: unexpected sock %d != %d",
704			   __func__, sock, t->pipefd1[0]);
705	}
706
707	res = read(sock, buf, sizeof(buf));
708	wpa_printf(MSG_INFO, "%s: sock=%d --> res=%d",
709		   __func__, sock, (int) res);
710
711	if (!t->close_in_timeout)
712		reopen_pipefd2(t);
713}
714
715
716static void eloop_test_cb(void *eloop_data, void *user_ctx)
717{
718	struct test_eloop *t = eloop_data;
719
720	wpa_printf(MSG_INFO, "%s", __func__);
721
722	if (t->magic != 0x12345678) {
723		wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
724			   __func__, t->magic);
725	}
726
727	if (t->close_in_timeout)
728		reopen_pipefd2(t);
729}
730
731
732static void eloop_test_timeout(void *eloop_data, void *user_ctx)
733{
734	struct test_eloop *t = eloop_data;
735	int next_run = 0;
736
737	wpa_printf(MSG_INFO, "%s", __func__);
738
739	if (t->magic != 0x12345678) {
740		wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
741			   __func__, t->magic);
742	}
743
744	if (t->pipefd1[0] >= 0) {
745		wpa_printf(MSG_INFO, "pipefd1 had not been closed");
746		eloop_unregister_read_sock(t->pipefd1[0]);
747		close(t->pipefd1[0]);
748		t->pipefd1[0] = -1;
749		close(t->pipefd1[1]);
750		t->pipefd1[1] = -1;
751	}
752
753	if (t->pipefd2[0] >= 0) {
754		wpa_printf(MSG_INFO, "pipefd2 had not been closed");
755		eloop_unregister_read_sock(t->pipefd2[0]);
756		close(t->pipefd2[0]);
757		t->pipefd2[0] = -1;
758		close(t->pipefd2[1]);
759		t->pipefd2[1] = -1;
760	}
761
762	next_run = t->close_in_timeout;
763	t->magic = 0;
764	wpa_printf(MSG_INFO, "%s - free(%p)", __func__, t);
765	os_free(t);
766
767	if (next_run)
768		eloop_tests_start(0);
769}
770
771
772static void eloop_tests_start(int close_in_timeout)
773{
774	struct test_eloop *t;
775	int res;
776
777	t = os_zalloc(sizeof(*t));
778	if (!t)
779		return;
780	t->magic = 0x12345678;
781	t->close_in_timeout = close_in_timeout;
782
783	wpa_printf(MSG_INFO, "starting eloop tests (%p) (close_in_timeout=%d)",
784		   t, close_in_timeout);
785
786	res = pipe(t->pipefd1);
787	if (res < 0) {
788		wpa_printf(MSG_INFO, "pipe: %s", strerror(errno));
789		os_free(t);
790		return;
791	}
792
793	res = pipe(t->pipefd2);
794	if (res < 0) {
795		wpa_printf(MSG_INFO, "pipe: %s", strerror(errno));
796		close(t->pipefd1[0]);
797		close(t->pipefd1[1]);
798		os_free(t);
799		return;
800	}
801
802	wpa_printf(MSG_INFO, "pipe fds: %d,%d %d,%d",
803		   t->pipefd1[0], t->pipefd1[1],
804		   t->pipefd2[0], t->pipefd2[1]);
805
806	eloop_register_read_sock(t->pipefd1[0], eloop_test_read_1, t, NULL);
807	eloop_register_read_sock(t->pipefd2[0], eloop_test_read_2, t, NULL);
808	eloop_register_timeout(0, 0, eloop_test_cb, t, NULL);
809	eloop_register_timeout(0, 200000, eloop_test_timeout, t, NULL);
810
811	if (write(t->pipefd1[1], "HELLO", 5) < 0)
812		wpa_printf(MSG_INFO, "write: %s", strerror(errno));
813	if (write(t->pipefd2[1], "TEST", 4) < 0)
814		wpa_printf(MSG_INFO, "write: %s", strerror(errno));
815	os_sleep(0, 50000);
816	wpa_printf(MSG_INFO, "waiting for eloop callbacks");
817}
818
819
820static void eloop_tests_run(void *eloop_data, void *user_ctx)
821{
822	eloop_tests_start(1);
823}
824
825
826static int eloop_tests(void)
827{
828	wpa_printf(MSG_INFO, "schedule eloop tests to be run");
829
830	/*
831	 * Cannot return error from these without a significant design change,
832	 * so for now, run the tests from a scheduled timeout and require
833	 * separate verification of the results from the debug log.
834	 */
835	eloop_register_timeout(0, 0, eloop_tests_run, NULL, NULL);
836
837	return 0;
838}
839
840
841int utils_module_tests(void)
842{
843	int ret = 0;
844
845	wpa_printf(MSG_INFO, "utils module tests");
846
847	if (printf_encode_decode_tests() < 0 ||
848	    ext_password_tests() < 0 ||
849	    trace_tests() < 0 ||
850	    bitfield_tests() < 0 ||
851	    base64_tests() < 0 ||
852	    common_tests() < 0 ||
853	    os_tests() < 0 ||
854	    wpabuf_tests() < 0 ||
855	    ip_addr_tests() < 0 ||
856	    eloop_tests() < 0 ||
857	    int_array_tests() < 0)
858		ret = -1;
859
860	return ret;
861}
862