dascandy / hippomocks

GNU Lesser General Public License v2.1
196 stars 67 forks source link

Mocking Static Functions #40

Closed kouberl closed 9 years ago

kouberl commented 9 years ago

I cannot catch any exception when mocking static functions. (using a decent g++ compiler under linux)

A minimal example: http://coliru.stacked-crooked.com/a/1f5ea78f50a29b3d

dascandy commented 9 years ago

Highly interesting. I've modified your case to add prints to find where it fails, but the moment I do that it stops failing & just works as intended.

http://pastebin.com/XCA12UV6

... Feels like a compiler issue, somehow. Perhaps it's rescheduling something it shouldn't?

dascandy commented 9 years ago

It stops failing as soon as the call to the mocked function is not the last function. Looks like GCC is inlining this function in -O0 in case it's a tail-recurse, but not otherwise.

One of the limitations of static function mocking is that your compiler should NOT inline them. I cannot mock an inlined function.

More interesting though, it looks like it closes the try... catch block before actually tail-recursing, even if it is not actually inlining the block.

dascandy commented 9 years ago

Modifying the original function to throw an exception fixes this behaviour. GCC uses its prior knowledge about the function to move it out of the try-catch block, which HippoMocks then modifies behind the scenes to throw an exception anyway, causing it to stop. Funny thing is that this also happens when you disable any and all inlining - literally attribute ((noinline)).

If you move the function external it will work. If your function is not deduced as "will not throw exception" otherwise, it's also fine.

dascandy commented 9 years ago

I've seen similar behaviour from MSVC, where noreturn functions cause the calling function to not have any code generated after the call to it, so if you'd mock "exit" to return 1, your program would just crash as there's no code to return to.

kouberl commented 9 years ago

Thank you for your efforts. That's interesting. Now I'm mocking extern functions, this works without complaining :-)