Attention is currently required from: Anastasia Klimchuk. Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/55934 )
Change subject: dediprog: Init-shutdown test for dediprog ......................................................................
Patch Set 3:
(2 comments)
File tests/io_mock.h:
https://review.coreboot.org/c/flashrom/+/55934/comment/bca06c00_85043fb4 PS3, Line 34: /* Define libusb symbols to avoid dependency on libusb.h */ Now that I realized that we don't mock `libusb.h` for the code under test. I wonder why we should avoid it here? It doesn't hurt so I'm ok with it. Just wondering.
(I guess it wouldn't be hard to build the tests without libusb, but that can still be done if anyone ever needs it.)
File tests/io_mock.h:
https://review.coreboot.org/c/flashrom/+/55934/comment/3c357fa5_e8df9617 PS2, Line 52: */
Done, it works! but I'm not sure I understand how it works... […]
Oh, I missed earlier that you avoid the libusb dependency here while it's still needed for the tests to build (includes of the code under test). There are some explanations why this works. Here is why this is legal in C:
* The typedef is somewhat transparent. You can repeat it whereever you want, as long as it's the same type. * Just saying `struct libusb_device_handle;` without a member list makes it an incomplete type. That's good enough to declare pointers as long as the compiler doesn't need to know the size of the type, i.e. we don't try to dereference anything. Strictly speaking, the type we use here is not `libusb_device_handle`, it is `pointer to libusb_device_handle`. * Naturally, if incomplete types are allowed, it must be allowed to mix them with the actual (complete) type in another compilation unit. Otherwise they would be rather useless.
(NB. Incomplete types are a means of information hiding in C.)
Here is my favorite explanation: It all doesn't matter ;) because the compiler only looks at compilation units individually. And the linker who stitches the compilation results of the various compilation units together doesn't know C and its types. It doesn't even have to know parameters. There's a call to a symbol, it replaces the symbol with an address. That's about it. To get a working program out of it, the compiler needs to know the size of the parameters, and the size needs to match across compilation units. All pointers have the same size in C which makes it work even if we'd use `int *` here.