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