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
18
19struct printf_test_data {
20	u8 *data;
21	size_t len;
22	char *encoded;
23};
24
25static const struct printf_test_data printf_tests[] = {
26	{ (u8 *) "abcde", 5, "abcde" },
27	{ (u8 *) "a\0b\nc\ed\re\tf\"\\", 13, "a\\0b\\nc\\ed\\re\\tf\\\"\\\\" },
28	{ (u8 *) "\x00\x31\x00\x32\x00\x39", 6, "\\x001\\0002\\09" },
29	{ (u8 *) "\n\n\n", 3, "\n\12\x0a" },
30	{ (u8 *) "\303\245\303\244\303\266\303\205\303\204\303\226", 12,
31	  "\\xc3\\xa5\xc3\\xa4\\xc3\\xb6\\xc3\\x85\\xc3\\x84\\xc3\\x96" },
32	{ (u8 *) "\303\245\303\244\303\266\303\205\303\204\303\226", 12,
33	  "\\303\\245\\303\\244\\303\\266\\303\\205\\303\\204\\303\\226" },
34	{ (u8 *) "\xe5\xe4\xf6\xc5\xc4\xd6", 6,
35	  "\\xe5\\xe4\\xf6\\xc5\\xc4\\xd6" },
36	{ NULL, 0, NULL }
37};
38
39
40static int printf_encode_decode_tests(void)
41{
42	int i;
43	size_t binlen;
44	char buf[100];
45	u8 bin[100];
46	int errors = 0;
47
48	wpa_printf(MSG_INFO, "printf encode/decode tests");
49
50	for (i = 0; printf_tests[i].data; i++) {
51		const struct printf_test_data *test = &printf_tests[i];
52		printf_encode(buf, sizeof(buf), test->data, test->len);
53		wpa_printf(MSG_INFO, "%d: -> \"%s\"", i, buf);
54
55		binlen = printf_decode(bin, sizeof(bin), buf);
56		if (binlen != test->len ||
57		    os_memcmp(bin, test->data, binlen) != 0) {
58			wpa_hexdump(MSG_ERROR, "Error in decoding#1",
59				    bin, binlen);
60			errors++;
61		}
62
63		binlen = printf_decode(bin, sizeof(bin), test->encoded);
64		if (binlen != test->len ||
65		    os_memcmp(bin, test->data, binlen) != 0) {
66			wpa_hexdump(MSG_ERROR, "Error in decoding#2",
67				    bin, binlen);
68			errors++;
69		}
70	}
71
72	buf[5] = 'A';
73	printf_encode(buf, 5, (const u8 *) "abcde", 5);
74	if (buf[5] != 'A') {
75		wpa_printf(MSG_ERROR, "Error in bounds checking#1");
76		errors++;
77	}
78
79	for (i = 5; i < 10; i++) {
80		buf[i] = 'A';
81		printf_encode(buf, i, (const u8 *) "\xdd\xdd\xdd\xdd\xdd", 5);
82		if (buf[i] != 'A') {
83			wpa_printf(MSG_ERROR, "Error in bounds checking#2(%d)",
84				   i);
85			errors++;
86		}
87	}
88
89	if (printf_decode(bin, 3, "abcde") != 2)
90		errors++;
91
92	if (printf_decode(bin, 3, "\\xa") != 1 || bin[0] != 10)
93		errors++;
94
95	if (printf_decode(bin, 3, "\\a") != 1 || bin[0] != 'a')
96		errors++;
97
98	if (errors) {
99		wpa_printf(MSG_ERROR, "%d printf test(s) failed", errors);
100		return -1;
101	}
102
103	return 0;
104}
105
106
107static int bitfield_tests(void)
108{
109	struct bitfield *bf;
110	int i;
111	int errors = 0;
112
113	wpa_printf(MSG_INFO, "bitfield tests");
114
115	bf = bitfield_alloc(123);
116	if (bf == NULL)
117		return -1;
118
119	for (i = 0; i < 123; i++) {
120		if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1))
121			errors++;
122		if (i > 0 && bitfield_is_set(bf, i - 1))
123			errors++;
124		bitfield_set(bf, i);
125		if (!bitfield_is_set(bf, i))
126			errors++;
127		bitfield_clear(bf, i);
128		if (bitfield_is_set(bf, i))
129			errors++;
130	}
131
132	for (i = 123; i < 200; i++) {
133		if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1))
134			errors++;
135		if (i > 0 && bitfield_is_set(bf, i - 1))
136			errors++;
137		bitfield_set(bf, i);
138		if (bitfield_is_set(bf, i))
139			errors++;
140		bitfield_clear(bf, i);
141		if (bitfield_is_set(bf, i))
142			errors++;
143	}
144
145	for (i = 0; i < 123; i++) {
146		if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1))
147			errors++;
148		bitfield_set(bf, i);
149		if (!bitfield_is_set(bf, i))
150			errors++;
151	}
152
153	for (i = 0; i < 123; i++) {
154		if (!bitfield_is_set(bf, i))
155			errors++;
156		bitfield_clear(bf, i);
157		if (bitfield_is_set(bf, i))
158			errors++;
159	}
160
161	for (i = 0; i < 123; i++) {
162		if (bitfield_get_first_zero(bf) != i)
163			errors++;
164		bitfield_set(bf, i);
165	}
166	if (bitfield_get_first_zero(bf) != -1)
167		errors++;
168	for (i = 0; i < 123; i++) {
169		if (!bitfield_is_set(bf, i))
170			errors++;
171		bitfield_clear(bf, i);
172		if (bitfield_get_first_zero(bf) != i)
173			errors++;
174		bitfield_set(bf, i);
175	}
176	if (bitfield_get_first_zero(bf) != -1)
177		errors++;
178
179	bitfield_free(bf);
180
181	bf = bitfield_alloc(8);
182	if (bf == NULL)
183		return -1;
184	if (bitfield_get_first_zero(bf) != 0)
185		errors++;
186	for (i = 0; i < 8; i++)
187		bitfield_set(bf, i);
188	if (bitfield_get_first_zero(bf) != -1)
189		errors++;
190	bitfield_free(bf);
191
192	if (errors) {
193		wpa_printf(MSG_ERROR, "%d bitfield test(s) failed", errors);
194		return -1;
195	}
196
197	return 0;
198}
199
200
201static int int_array_tests(void)
202{
203	int test1[] = { 1, 2, 3, 4, 5, 6, 0 };
204	int test2[] = { 1, -1, 0 };
205	int test3[] = { 1, 1, 1, -1, 2, 3, 4, 1, 2, 0 };
206	int test3_res[] = { -1, 1, 2, 3, 4, 0 };
207	int errors = 0;
208	int len;
209
210	wpa_printf(MSG_INFO, "int_array tests");
211
212	if (int_array_len(test1) != 6 ||
213	    int_array_len(test2) != 2)
214		errors++;
215
216	int_array_sort_unique(test3);
217	len = int_array_len(test3_res);
218	if (int_array_len(test3) != len)
219		errors++;
220	else if (os_memcmp(test3, test3_res, len * sizeof(int)) != 0)
221		errors++;
222
223	if (errors) {
224		wpa_printf(MSG_ERROR, "%d int_array test(s) failed", errors);
225		return -1;
226	}
227
228	return 0;
229}
230
231
232static int ext_password_tests(void)
233{
234	struct ext_password_data *data;
235	int ret = 0;
236	struct wpabuf *pw;
237
238	wpa_printf(MSG_INFO, "ext_password tests");
239
240	data = ext_password_init("unknown", "foo");
241	if (data != NULL)
242		return -1;
243
244	data = ext_password_init("test", NULL);
245	if (data == NULL)
246		return -1;
247	pw = ext_password_get(data, "foo");
248	if (pw != NULL)
249		ret = -1;
250	ext_password_free(pw);
251
252	ext_password_deinit(data);
253
254	pw = ext_password_get(NULL, "foo");
255	if (pw != NULL)
256		ret = -1;
257	ext_password_free(pw);
258
259	return ret;
260}
261
262
263static int trace_tests(void)
264{
265	wpa_printf(MSG_INFO, "trace tests");
266
267	wpa_trace_show("test backtrace");
268	wpa_trace_dump_funcname("test funcname", trace_tests);
269
270	return 0;
271}
272
273
274static int base64_tests(void)
275{
276	int errors = 0;
277	unsigned char *res;
278	size_t res_len;
279
280	wpa_printf(MSG_INFO, "base64 tests");
281
282	res = base64_encode((const unsigned char *) "", ~0, &res_len);
283	if (res) {
284		errors++;
285		os_free(res);
286	}
287
288	res = base64_encode((const unsigned char *) "=", 1, &res_len);
289	if (!res || res_len != 5 || res[0] != 'P' || res[1] != 'Q' ||
290	    res[2] != '=' || res[3] != '=' || res[4] != '\n')
291		errors++;
292	os_free(res);
293
294	res = base64_encode((const unsigned char *) "=", 1, NULL);
295	if (!res || res[0] != 'P' || res[1] != 'Q' ||
296	    res[2] != '=' || res[3] != '=' || res[4] != '\n')
297		errors++;
298	os_free(res);
299
300	res = base64_decode((const unsigned char *) "", 0, &res_len);
301	if (res) {
302		errors++;
303		os_free(res);
304	}
305
306	res = base64_decode((const unsigned char *) "a", 1, &res_len);
307	if (res) {
308		errors++;
309		os_free(res);
310	}
311
312	res = base64_decode((const unsigned char *) "====", 4, &res_len);
313	if (res) {
314		errors++;
315		os_free(res);
316	}
317
318	res = base64_decode((const unsigned char *) "PQ==", 4, &res_len);
319	if (!res || res_len != 1 || res[0] != '=')
320		errors++;
321	os_free(res);
322
323	res = base64_decode((const unsigned char *) "P.Q-=!=*", 8, &res_len);
324	if (!res || res_len != 1 || res[0] != '=')
325		errors++;
326	os_free(res);
327
328	if (errors) {
329		wpa_printf(MSG_ERROR, "%d base64 test(s) failed", errors);
330		return -1;
331	}
332
333	return 0;
334}
335
336
337static int common_tests(void)
338{
339	char buf[3];
340	u8 addr[ETH_ALEN] = { 1, 2, 3, 4, 5, 6 };
341	u8 bin[3];
342	int errors = 0;
343	struct wpa_freq_range_list ranges;
344	size_t len;
345	const char *txt;
346	u8 ssid[255];
347
348	wpa_printf(MSG_INFO, "common tests");
349
350	if (hwaddr_mask_txt(buf, 3, addr, addr) != -1)
351		errors++;
352
353	if (wpa_scnprintf(buf, 0, "hello") != 0 ||
354	    wpa_scnprintf(buf, 3, "hello") != 2)
355		errors++;
356
357	if (wpa_snprintf_hex(buf, 0, addr, ETH_ALEN) != 0 ||
358	    wpa_snprintf_hex(buf, 3, addr, ETH_ALEN) != 2)
359		errors++;
360
361	if (merge_byte_arrays(bin, 3, addr, ETH_ALEN, NULL, 0) != 3 ||
362	    merge_byte_arrays(bin, 3, NULL, 0, addr, ETH_ALEN) != 3)
363		errors++;
364
365	if (dup_binstr(NULL, 0) != NULL)
366		errors++;
367
368	if (freq_range_list_includes(NULL, 0) != 0)
369		errors++;
370
371	os_memset(&ranges, 0, sizeof(ranges));
372	if (freq_range_list_parse(&ranges, "") != 0 ||
373	    freq_range_list_includes(&ranges, 0) != 0 ||
374	    freq_range_list_str(&ranges) != NULL)
375		errors++;
376
377	if (utf8_unescape(NULL, 0, buf, sizeof(buf)) != 0 ||
378	    utf8_unescape("a", 1, NULL, 0) != 0 ||
379	    utf8_unescape("a\\", 2, buf, sizeof(buf)) != 0 ||
380	    utf8_unescape("abcde", 5, buf, sizeof(buf)) != 0 ||
381	    utf8_unescape("abc", 3, buf, 3) != 3)
382		errors++;
383
384	if (utf8_unescape("a", 0, buf, sizeof(buf)) != 1 || buf[0] != 'a')
385		errors++;
386
387	if (utf8_unescape("\\b", 2, buf, sizeof(buf)) != 1 || buf[0] != 'b')
388		errors++;
389
390	if (utf8_escape(NULL, 0, buf, sizeof(buf)) != 0 ||
391	    utf8_escape("a", 1, NULL, 0) != 0 ||
392	    utf8_escape("abcde", 5, buf, sizeof(buf)) != 0 ||
393	    utf8_escape("a\\bcde", 6, buf, sizeof(buf)) != 0 ||
394	    utf8_escape("ab\\cde", 6, buf, sizeof(buf)) != 0 ||
395	    utf8_escape("abc\\de", 6, buf, sizeof(buf)) != 0 ||
396	    utf8_escape("abc", 3, buf, 3) != 3)
397		errors++;
398
399	if (utf8_escape("a", 0, buf, sizeof(buf)) != 1 || buf[0] != 'a')
400		errors++;
401
402	os_memset(ssid, 0, sizeof(ssid));
403	txt = wpa_ssid_txt(ssid, sizeof(ssid));
404	len = os_strlen(txt);
405	/* Verify that SSID_MAX_LEN * 4 buffer limit is enforced. */
406	if (len != SSID_MAX_LEN * 4) {
407		wpa_printf(MSG_ERROR,
408			   "Unexpected wpa_ssid_txt() result with too long SSID");
409		errors++;
410	}
411
412	if (errors) {
413		wpa_printf(MSG_ERROR, "%d common test(s) failed", errors);
414		return -1;
415	}
416
417	return 0;
418}
419
420
421int utils_module_tests(void)
422{
423	int ret = 0;
424
425	wpa_printf(MSG_INFO, "utils module tests");
426
427	if (printf_encode_decode_tests() < 0 ||
428	    ext_password_tests() < 0 ||
429	    trace_tests() < 0 ||
430	    bitfield_tests() < 0 ||
431	    base64_tests() < 0 ||
432	    common_tests() < 0 ||
433	    int_array_tests() < 0)
434		ret = -1;
435
436	return ret;
437}
438