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