xref: /aosp_15_r20/external/flashrom/tests/tests.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1 /*
2  * This file is part of the flashrom project.
3  *
4  * Copyright 2020 Google LLC
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15 
16 #include <include/test.h>
17 #include "io_mock.h"
18 #include "tests.h"
19 #include "wraps.h"
20 #include "io_real.h"
21 
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdint.h>
25 #include <pthread.h>
26 
not_null(void)27 void *not_null(void)
28 {
29 	return (void *)MOCK_FD;
30 }
31 
32 /* Workaround for https://github.com/clibs/cmocka/issues/17 */
__wrap_strdup(const char * s)33 char *__wrap_strdup(const char *s)
34 {
35 	size_t len = strlen(s) + 1;
36 	void *new = malloc(len);
37 	if (new == NULL)
38 		return NULL;
39 	return (char *)memcpy(new, s, len);
40 }
41 
__wrap_physunmap(void * virt_addr,size_t len)42 void __wrap_physunmap(void *virt_addr, size_t len)
43 {
44 	LOG_ME;
45 }
46 
__wrap_physmap(const char * descr,uintptr_t phys_addr,size_t len)47 void *__wrap_physmap(const char *descr, uintptr_t phys_addr, size_t len)
48 {
49 	LOG_ME;
50 	return NULL;
51 }
52 
53 struct pci_dev mock_pci_dev = {
54 	.device_id = NON_ZERO,
55 };
56 
__wrap_pcidev_init(const struct programmer_cfg * cfg,void * devs,int bar)57 struct pci_dev *__wrap_pcidev_init(const struct programmer_cfg *cfg, void *devs, int bar)
58 {
59 	LOG_ME;
60 	return &mock_pci_dev;
61 }
62 
__wrap_pcidev_readbar(void * dev,int bar)63 uintptr_t __wrap_pcidev_readbar(void *dev, int bar)
64 {
65 	LOG_ME;
66 	return NON_ZERO;
67 }
68 
__wrap_sio_write(uint16_t port,uint8_t reg,uint8_t data)69 void __wrap_sio_write(uint16_t port, uint8_t reg, uint8_t data)
70 {
71 	LOG_ME;
72 }
73 
__wrap_sio_read(uint16_t port,uint8_t reg)74 uint8_t __wrap_sio_read(uint16_t port, uint8_t reg)
75 {
76 	LOG_ME;
77 	return (uint8_t)mock();
78 }
79 
mock_open(const char * pathname,int flags,mode_t mode)80 static int mock_open(const char *pathname, int flags, mode_t mode)
81 {
82 	maybe_unmock_io(pathname);
83 	if (get_io() && get_io()->iom_open)
84 		return get_io()->iom_open(get_io()->state, pathname, flags, mode);
85 
86 	if (get_io() && get_io()->fallback_open_state) {
87 		struct io_mock_fallback_open_state *io_state;
88 		unsigned int open_state_flags;
89 
90 		io_state = get_io()->fallback_open_state;
91 		assert_true(io_state->noc < MAX_MOCK_OPEN);
92 		assert_non_null(io_state->paths[io_state->noc]);
93 		assert_string_equal(pathname, io_state->paths[io_state->noc]);
94 		open_state_flags = io_state->flags[io_state->noc];
95 		assert_int_equal(flags & open_state_flags, open_state_flags);
96 		io_state->noc++; // proceed to the next path upon next call.
97 	}
98 
99 	return MOCK_FD;
100 }
101 
__wrap_open(const char * pathname,int flags,...)102 int __wrap_open(const char *pathname, int flags, ...)
103 {
104 	LOG_ME;
105 	int mode = 0;
106 	if (flags & O_CREAT) {
107 		va_list ap;
108 		va_start(ap, flags);
109 		mode = va_arg(ap, int);
110 		va_end(ap);
111 	}
112 	return mock_open(pathname, flags, (mode_t) mode);
113 }
114 
__wrap_open64(const char * pathname,int flags,...)115 int __wrap_open64(const char *pathname, int flags, ...)
116 {
117 	LOG_ME;
118 	int mode = 0;
119 	if (flags & O_CREAT) {
120 		va_list ap;
121 		va_start(ap, flags);
122 		mode = va_arg(ap, int);
123 		va_end(ap);
124 	}
125 	return mock_open(pathname, flags, (mode_t) mode);
126 }
127 
__wrap___open64_2(const char * pathname,int flags,...)128 int __wrap___open64_2(const char *pathname, int flags, ...)
129 {
130 	LOG_ME;
131 	int mode = 0;
132 	if (flags & O_CREAT) {
133 		va_list ap;
134 		va_start(ap, flags);
135 		mode = va_arg(ap, int);
136 		va_end(ap);
137 	}
138 	return mock_open(pathname, flags, (mode_t) mode);
139 }
140 
__wrap_ioctl(int fd,unsigned long int request,...)141 int __wrap_ioctl(int fd, unsigned long int request, ...)
142 {
143 	LOG_ME;
144 	if (get_io() && get_io()->iom_ioctl) {
145 		va_list args;
146 		int out;
147 		va_start(args, request);
148 		out = get_io()->iom_ioctl(get_io()->state, fd, request, args);
149 		va_end(args);
150 		return out;
151 	}
152 	return 0;
153 }
154 
__wrap_write(int fd,const void * buf,size_t sz)155 int __wrap_write(int fd, const void *buf, size_t sz)
156 {
157 	LOG_ME;
158 	if (get_io() && get_io()->iom_write)
159 		return get_io()->iom_write(get_io()->state, fd, buf, sz);
160 	return sz;
161 }
162 
__wrap_read(int fd,void * buf,size_t sz)163 int __wrap_read(int fd, void *buf, size_t sz)
164 {
165 	LOG_ME;
166 	if (get_io() && get_io()->iom_read)
167 		return get_io()->iom_read(get_io()->state, fd, buf, sz);
168 	return sz;
169 }
170 
__wrap_fopen(const char * pathname,const char * mode)171 FILE *__wrap_fopen(const char *pathname, const char *mode)
172 {
173 	LOG_ME;
174 	maybe_unmock_io(pathname);
175 	if (get_io() && get_io()->iom_fopen)
176 		return get_io()->iom_fopen(get_io()->state, pathname, mode);
177 	return not_null();
178 }
179 
__wrap_fopen64(const char * pathname,const char * mode)180 FILE *__wrap_fopen64(const char *pathname, const char *mode)
181 {
182 	LOG_ME;
183 	maybe_unmock_io(pathname);
184 	if (get_io() && get_io()->iom_fopen)
185 		return get_io()->iom_fopen(get_io()->state, pathname, mode);
186 	return not_null();
187 }
188 
__wrap_fdopen(int fd,const char * mode)189 FILE *__wrap_fdopen(int fd, const char *mode)
190 {
191 	LOG_ME;
192 	if (get_io() && get_io()->iom_fdopen)
193 		return get_io()->iom_fdopen(get_io()->state, fd, mode);
194 	return not_null();
195 }
196 
__wrap_stat(const char * path,void * buf)197 int __wrap_stat(const char *path, void *buf)
198 {
199 	LOG_ME;
200 	return 1;
201 }
202 
__wrap_stat64(const char * path,void * buf)203 int __wrap_stat64(const char *path, void *buf)
204 {
205 	LOG_ME;
206 	return 1;
207 }
208 
__wrap___xstat(const char * path,void * buf)209 int __wrap___xstat(const char *path, void *buf)
210 {
211 	LOG_ME;
212 	return 0;
213 }
214 
__wrap___xstat64(const char * path,void * buf)215 int __wrap___xstat64(const char *path, void *buf)
216 {
217 	LOG_ME;
218 	return 0;
219 }
220 
__wrap_fstat(int fd,void * buf)221 int __wrap_fstat(int fd, void *buf)
222 {
223 	LOG_ME;
224 	return 0;
225 }
226 
__wrap_fstat64(int fd,void * buf)227 int __wrap_fstat64(int fd, void *buf)
228 {
229 	LOG_ME;
230 	return 0;
231 }
232 
__wrap___fstat50(int fd,void * buf)233 int __wrap___fstat50(int fd, void *buf)
234 {
235 	LOG_ME;
236 	return 0;
237 }
238 
__wrap___fxstat(int fd,void * buf)239 int __wrap___fxstat(int fd, void *buf)
240 {
241 	LOG_ME;
242 	return 0;
243 }
244 
__wrap___fxstat64(int fd,void * buf)245 int __wrap___fxstat64(int fd, void *buf)
246 {
247 	LOG_ME;
248 	return 0;
249 }
250 
__wrap_fgets(char * buf,int len,FILE * fp)251 char *__wrap_fgets(char *buf, int len, FILE *fp)
252 {
253 	LOG_ME;
254 	if (get_io() && get_io()->iom_fgets)
255 		return get_io()->iom_fgets(get_io()->state, buf, len, fp);
256 	return NULL;
257 }
258 
__wrap_fread(void * ptr,size_t size,size_t nmemb,FILE * fp)259 size_t __wrap_fread(void *ptr, size_t size, size_t nmemb, FILE *fp)
260 {
261 	LOG_ME;
262 	if (get_io() && get_io()->iom_fread)
263 		return get_io()->iom_fread(get_io()->state, ptr, size, nmemb, fp);
264 	return nmemb;
265 }
266 
__wrap_fwrite(const void * ptr,size_t size,size_t nmemb,FILE * fp)267 size_t __wrap_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp)
268 {
269 	LOG_ME;
270 	if (get_io() && get_io()->iom_fwrite)
271 		return get_io()->iom_fwrite(get_io()->state, ptr, size, nmemb, fp);
272 	return nmemb;
273 }
274 
__wrap_fflush(FILE * fp)275 int __wrap_fflush(FILE *fp)
276 {
277 	LOG_ME;
278 	return 0;
279 }
280 
__wrap_fileno(FILE * fp)281 int __wrap_fileno(FILE *fp)
282 {
283 	LOG_ME;
284 	return MOCK_FD;
285 }
286 
__wrap_fsync(int fd)287 int __wrap_fsync(int fd)
288 {
289 	LOG_ME;
290 	return 0;
291 }
292 
__wrap_setvbuf(FILE * fp,char * buf,int type,size_t size)293 int __wrap_setvbuf(FILE *fp, char *buf, int type, size_t size)
294 {
295 	LOG_ME;
296 	return 0;
297 }
298 
__wrap_fprintf(FILE * fp,const char * fmt,...)299 int __wrap_fprintf(FILE *fp, const char *fmt, ...)
300 {
301 	LOG_ME;
302 	if (get_io() && get_io()->iom_fprintf) {
303 		va_list args;
304 		int out;
305 		va_start(args, fmt);
306 		out = get_io()->iom_fprintf(get_io()->state, fp, fmt, args);
307 		va_end(args);
308 		return out;
309 	}
310 	return 0;
311 }
312 
__wrap_fclose(FILE * fp)313 int __wrap_fclose(FILE *fp)
314 {
315 	LOG_ME;
316 	if (get_io() && get_io()->iom_fclose)
317 		return get_io()->iom_fclose(get_io()->state, fp);
318 	return 0;
319 }
320 
__wrap_feof(FILE * fp)321 int __wrap_feof(FILE *fp)
322 {
323 	/* LOG_ME; */
324 	return 0;
325 }
326 
__wrap_ferror(FILE * fp)327 int __wrap_ferror(FILE *fp)
328 {
329 	/* LOG_ME; */
330 	return 0;
331 }
332 
__wrap_flock(int fd,int operation)333 int __wrap_flock(int fd, int operation)
334 {
335 	LOG_ME;
336 	return 0;
337 }
338 
__wrap_ftruncate(int fd,off_t length)339 int __wrap_ftruncate(int fd, off_t length)
340 {
341 	LOG_ME;
342 	return 0;
343 }
344 
__wrap_clearerr(FILE * fp)345 void __wrap_clearerr(FILE *fp)
346 {
347 	/* LOG_ME; */
348 	return;
349 }
350 
__wrap_rget_io_perms(void)351 int __wrap_rget_io_perms(void)
352 {
353 	LOG_ME;
354 	return 0;
355 }
356 
__wrap_OUTB(unsigned char value,unsigned short port)357 void __wrap_OUTB(unsigned char value, unsigned short port)
358 {
359 	/* LOG_ME; */
360 	if (get_io() && get_io()->outb)
361 		get_io()->outb(get_io()->state, value, port);
362 }
363 
__wrap_INB(unsigned short port)364 unsigned char __wrap_INB(unsigned short port)
365 {
366 	/* LOG_ME; */
367 	if (get_io() && get_io()->inb)
368 		return get_io()->inb(get_io()->state, port);
369 	return 0;
370 }
371 
__wrap_OUTW(unsigned short value,unsigned short port)372 void __wrap_OUTW(unsigned short value, unsigned short port)
373 {
374 	/* LOG_ME; */
375 	if (get_io() && get_io()->outw)
376 		get_io()->outw(get_io()->state, value, port);
377 }
378 
__wrap_INW(unsigned short port)379 unsigned short __wrap_INW(unsigned short port)
380 {
381 	/* LOG_ME; */
382 	if (get_io() && get_io()->inw)
383 		return get_io()->inw(get_io()->state, port);
384 	return 0;
385 }
386 
__wrap_OUTL(unsigned int value,unsigned short port)387 void __wrap_OUTL(unsigned int value, unsigned short port)
388 {
389 	/* LOG_ME; */
390 	if (get_io() && get_io()->outl)
391 		get_io()->outl(get_io()->state, value, port);
392 }
393 
__wrap_INL(unsigned short port)394 unsigned int __wrap_INL(unsigned short port)
395 {
396 	/* LOG_ME; */
397 	if (get_io() && get_io()->inl)
398 		return get_io()->inl(get_io()->state, port);
399 	return 0;
400 }
401 
doing_nothing(void * vargp)402 static void *doing_nothing(void *vargp) {
403 	return NULL;
404 }
405 
main(int argc,char * argv[])406 int main(int argc, char *argv[])
407 {
408 	int ret = 0;
409 
410 	if (argc > 1)
411 		cmocka_set_test_filter(argv[1]);
412 
413 	cmocka_set_message_output(CM_OUTPUT_STDOUT);
414 
415 	/*
416 	 * Creating new thread which is doing nothing, to trigger __isthreaded being 1.
417 	 * This is a workaround for BSD family. In multi-threaded environment fileno
418 	 * macro is expanded into a function which is possible to mock in unit tests.
419 	 * Without this workaround, on a single-thread environment, fileno macro is
420 	 * expanded into an inline access of a private field of a file descriptor,
421 	 * which is impossible to mock.
422 	 *
423 	 * In other OSes this is just creating a thread which is doing nothing.
424 	 */
425 	pthread_t thread_id;
426 	pthread_create(&thread_id, NULL, doing_nothing, NULL);
427 
428 	const struct CMUnitTest helpers_tests[] = {
429 		cmocka_unit_test(address_to_bits_test_success),
430 		cmocka_unit_test(bitcount_test_success),
431 		cmocka_unit_test(minmax_test_success),
432 		cmocka_unit_test(strcat_realloc_test_success),
433 		cmocka_unit_test(tolower_string_test_success),
434 		cmocka_unit_test(reverse_byte_test_success),
435 		cmocka_unit_test(reverse_bytes_test_success),
436 	};
437 	ret |= cmocka_run_group_tests_name("helpers.c tests", helpers_tests, NULL, NULL);
438 
439 	const struct CMUnitTest selfcheck[] = {
440 		cmocka_unit_test(selfcheck_programmer_table),
441 		cmocka_unit_test(selfcheck_flashchips_table),
442 		cmocka_unit_test(selfcheck_eraseblocks),
443 		cmocka_unit_test(selfcheck_board_matches_table),
444 	};
445 	ret |= cmocka_run_group_tests_name("selfcheck.c tests", selfcheck,
446 					   NULL, NULL);
447 
448 	const struct CMUnitTest flashrom_tests[] = {
449 		cmocka_unit_test(flashbuses_to_text_test_success),
450 	};
451 	ret |= cmocka_run_group_tests_name("flashrom.c tests", flashrom_tests, NULL, NULL);
452 
453 	const struct CMUnitTest spi25_tests[] = {
454 		cmocka_unit_test(spi_write_enable_test_success),
455 		cmocka_unit_test(spi_write_disable_test_success),
456 		cmocka_unit_test(spi_read_chunked_test_success),
457 		cmocka_unit_test(probe_spi_rdid_test_success),
458 		cmocka_unit_test(probe_spi_rdid4_test_success),
459 		cmocka_unit_test(probe_spi_rems_test_success),
460 		cmocka_unit_test(probe_spi_res1_test_success),
461 		cmocka_unit_test(probe_spi_res2_test_success),
462 		cmocka_unit_test(probe_spi_res3_test_success),
463 		cmocka_unit_test(probe_spi_at25f_test_success),
464 		cmocka_unit_test(probe_spi_st95_test_success), /* spi95.c */
465 	};
466 	ret |= cmocka_run_group_tests_name("spi25.c tests", spi25_tests, NULL, NULL);
467 
468 	const struct CMUnitTest lifecycle_tests[] = {
469 		cmocka_unit_test(dummy_basic_lifecycle_test_success),
470 		cmocka_unit_test(dummy_probe_lifecycle_test_success),
471 		cmocka_unit_test(dummy_probe_variable_size_test_success),
472 		cmocka_unit_test(dummy_init_fails_unhandled_param_test_success),
473 		cmocka_unit_test(dummy_init_success_invalid_param_test_success),
474 		cmocka_unit_test(dummy_init_success_unhandled_param_test_success),
475 		cmocka_unit_test(dummy_null_prog_param_test_success),
476 		cmocka_unit_test(dummy_all_buses_test_success),
477 		cmocka_unit_test(dummy_freq_param_init),
478 		cmocka_unit_test(nicrealtek_basic_lifecycle_test_success),
479 		cmocka_unit_test(raiden_debug_basic_lifecycle_test_success),
480 		cmocka_unit_test(raiden_debug_targetAP_basic_lifecycle_test_success),
481 		cmocka_unit_test(raiden_debug_targetEC_basic_lifecycle_test_success),
482 		cmocka_unit_test(raiden_debug_target0_basic_lifecycle_test_success),
483 		cmocka_unit_test(raiden_debug_target1_basic_lifecycle_test_success),
484 		cmocka_unit_test(dediprog_basic_lifecycle_test_success),
485 		cmocka_unit_test(linux_mtd_probe_lifecycle_test_success),
486 		cmocka_unit_test(linux_spi_probe_lifecycle_test_success),
487 		cmocka_unit_test(parade_lspcon_basic_lifecycle_test_success),
488 		cmocka_unit_test(parade_lspcon_no_allow_brick_test_success),
489 		cmocka_unit_test(mediatek_i2c_spi_basic_lifecycle_test_success),
490 		cmocka_unit_test(mediatek_i2c_no_allow_brick_test_success),
491 		cmocka_unit_test(realtek_mst_basic_lifecycle_test_success),
492 		cmocka_unit_test(realtek_mst_no_allow_brick_test_success),
493 		cmocka_unit_test(ch341a_spi_basic_lifecycle_test_success),
494 		cmocka_unit_test(ch341a_spi_probe_lifecycle_test_success),
495 	};
496 	ret |= cmocka_run_group_tests_name("lifecycle.c tests", lifecycle_tests, NULL, NULL);
497 
498 	const struct CMUnitTest layout_tests[] = {
499 		cmocka_unit_test(included_regions_dont_overlap_test_success),
500 		cmocka_unit_test(included_regions_overlap_test_success),
501 		cmocka_unit_test(region_not_included_overlap_test_success),
502 		cmocka_unit_test(layout_pass_sanity_checks_test_success),
503 		cmocka_unit_test(layout_region_invalid_address_test_success),
504 		cmocka_unit_test(layout_region_invalid_range_test_success),
505 	};
506 	ret |= cmocka_run_group_tests_name("layout.c tests", layout_tests, NULL, NULL);
507 
508 	const struct CMUnitTest chip_tests[] = {
509 		cmocka_unit_test(erase_chip_test_success),
510 		cmocka_unit_test(erase_chip_with_dummyflasher_test_success),
511 		cmocka_unit_test(read_chip_test_success),
512 		cmocka_unit_test(read_chip_with_dummyflasher_test_success),
513 		cmocka_unit_test(write_chip_test_success),
514 		cmocka_unit_test(write_chip_with_dummyflasher_test_success),
515 		cmocka_unit_test(write_chip_feature_no_erase),
516 		cmocka_unit_test(write_nonaligned_region_with_dummyflasher_test_success),
517 		cmocka_unit_test(verify_chip_test_success),
518 		cmocka_unit_test(verify_chip_with_dummyflasher_test_success),
519 	};
520 	ret |= cmocka_run_group_tests_name("chip.c tests", chip_tests, NULL, NULL);
521 
522 	const struct CMUnitTest chip_wp_tests[] = {
523 		cmocka_unit_test(invalid_wp_range_dummyflasher_test_success),
524 		cmocka_unit_test(set_wp_range_dummyflasher_test_success),
525 		cmocka_unit_test(switch_wp_mode_dummyflasher_test_success),
526 		cmocka_unit_test(wp_init_from_status_dummyflasher_test_success),
527 		cmocka_unit_test(full_chip_erase_with_wp_dummyflasher_test_success),
528 		cmocka_unit_test(partial_chip_erase_with_wp_dummyflasher_test_success),
529 		cmocka_unit_test(wp_get_register_values_and_masks),
530 	};
531 	ret |= cmocka_run_group_tests_name("chip_wp.c tests", chip_wp_tests, NULL, NULL);
532 
533 	return ret;
534 }
535