Home | History | Annotate | Download | only in utils
      1 /*
      2  * utils module tests
      3  * Copyright (c) 2014-2015, Jouni Malinen <j (at) 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 
     21 struct printf_test_data {
     22 	u8 *data;
     23 	size_t len;
     24 	char *encoded;
     25 };
     26 
     27 static 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 
     42 static 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 
    125 static 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 
    219 static 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 
    250 static 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 
    281 static 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 
    292 static 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 
    355 static 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 
    444 static 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 
    509 static 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 
    565 static 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 
    596 struct test_eloop {
    597 	unsigned int magic;
    598 	int close_in_timeout;
    599 	int pipefd1[2];
    600 	int pipefd2[2];
    601 };
    602 
    603 
    604 static void eloop_tests_start(int close_in_timeout);
    605 
    606 
    607 static 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 
    631 static 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 
    658 static 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 
    689 static 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 
    716 static 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 
    732 static 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 
    772 static 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 
    820 static void eloop_tests_run(void *eloop_data, void *user_ctx)
    821 {
    822 	eloop_tests_start(1);
    823 }
    824 
    825 
    826 static 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 
    841 int 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