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