fff icon indicating copy to clipboard operation
fff copied to clipboard

Variadic macro extensions to the FFF

Open cormacc opened this issue 6 years ago • 39 comments

This uses some VA_ARGS counting and iteration macros to reduce the boilerplate required when verifying calls to functions with multiple parameters, setting up return value sequences etc. Also allows to check for any call to a given function with a specified set of parameters.

Useful in my own codebase at least (embedded C) -- may be of more general interest.

This is a proposal for a PR for now. Packaged as two separate headers for clarity, and to save myself a bit of effort if you're not interested in adding the functionality - I'll integrate them with your generator if you confirm interest. The va_args iteration macros in vaiter64.h are already ruby-generated anyway.

See header comment in fff_ext.h for details -- summary extracted below:

N.B. tested with GCC

Return value macros:

FFF_RETURN(function_name, ...) Accepts a raw list of appropriately typed values

Assertion macros:

FFF_ASSERT_CALLS(function_name, expected_call_count)

FFF_ASSERT_CALLED(function_name) Only one call made to the function.

FFF_ASSERT_NOT_CALLED(function_name) No calls made to the function

FFF_ASSERT(function_name, ...parameters) Only one call made to the function (verifies parameter values if provided).

FFF_ASSERT_LAST(function_name, ...parameters) The final call to this function was made with the specified parameter values.

FFF_ASSERT_ANY(function_name, ...parameters) At least one call was made with the specified parameter values.

FFF_ASSERT_NONE(function_name, ...parameters) No calls were made with the specified parameter values.

FFF_ASSERT_NTH(function_name, call_index, ...parameters) A specified invocation of the function used the specified parameter values.

The assertion macros use <assert.h> by default, but overridable. I'm using Ceedling/Unity, and do this: `` #define _FFF_ASSERT_EQ_MSG(expected, actual, message) TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)

#include "fff.h" ``

Cobbled these together while switching an existing codebase from using cmock -- much happier with the approach adopted by the fff -- allows me to construct less brittle tests. Thanks for the tool

cormacc avatar Apr 05 '18 12:04 cormacc

This would make a very good addition. I've had to write these boilerplate several times.

rubiot avatar Apr 06 '18 12:04 rubiot

This looks good to me...thanks for taking the time to contribute!

Some ways forward I can see:

  • Integrate with the generator
  • Need to provide unit tests
  • Some documentation updates

meekrosoft avatar Apr 06 '18 12:04 meekrosoft

Great! Busy with family over the weekend, but should get back to it early next week.

On Fri, 6 Apr 2018 at 13:19 Mike Long [email protected] wrote:

This looks good to me...thanks for taking the time to contribute!

Some ways forward I can see:

  • Integrate with the generator
  • Need to provide unit tests
  • Some documentation updates

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/meekrosoft/fff/pull/48#issuecomment-379236320, or mute the thread https://github.com/notifications/unsubscribe-auth/ADmzi5qYxaLs-SbfIH4P0v_0q18e6ZBuks5tl11egaJpZM4TIWTz .

cormacc avatar Apr 06 '18 18:04 cormacc

Great! Busy with the family over the weekend, but should get back to it early next week.

cormacc avatar Apr 06 '18 18:04 cormacc

FYI, I've eliminated SET_RETURN_VAL and renaming SET_RETURN_VAL_SEQ to SET_RETURN, in the interest of API simplicity. Given that the behaviour when a sequence is exhausted is to repeat the last value,

MyFn_fake.ret_val = 3;

is functionally identical to

int retseq[] = {3};
SET_RETURN_VAL_SEQ(MyFn, retseq, 1);

even if the implementation is different under the hood, the end-user doesn't care. i.e.

SET_RETURN(MyFn, 1);
SET_RETURN(MyFn, 1, 2, 3);

cormacc avatar Apr 06 '18 22:04 cormacc

I've added unit tests, updated the generator and made some initial documentation updates. That probably needs a bit more but, @meekrosoft, you might have some preference for how you want the new functionality presented in relation to the existing interfaces? I've updated the hello world examples to show both syntaxes, and added most of the new functions to the cheat sheet.

I've renamed my args counting / iteration macros for consistency with what was there already and tried to maintain some consistency in the assertion function naming. Think that's it...

Oh, just added tests to the fff_test_c via a new .include file. Not sure on the relationship between the multiple test source files that include some of the same tests and didn't want to add them willy nilly.

cormacc avatar Apr 11 '18 18:04 cormacc

Great! I'm a bit snowed under with work, but I;ll take a look over the next couple of days....

meekrosoft avatar Apr 12 '18 18:04 meekrosoft

If you're wondering about the include guards around the PP_NARG macro definitions, they're because I use them in production code as well as test, and otherwise get a lot of noisy macro redefinition warnings when running tests.

cormacc avatar Apr 13 '18 10:04 cormacc

@cormacc, please resolve your conflicts before review moves forward.

wulfgarpro avatar Nov 23 '18 10:11 wulfgarpro

@wulfgarpro I'll definitely get back to this, but labouring under a pretty ridiculous workload til mid-january (one-man dev team in a medical device startup), and had actually gone a good way to a more concise set of vaargs macros based on some tail recursion ideas I came across in a blog post somewhere (i.e. don't have to hardcode a max arg count) since raising this PR, so . May well fit it in along the way, as I'm working on an embedded codebase that uses this. But could be as late as, well, late Jan. Well done for stepping in by the way -- just saw the cry for help post a few minutes ago -- great tool, would be a shame to let it fade away.

cormacc avatar Nov 24 '18 20:11 cormacc

... and January turns into June :S. The ridiculous workload lasted longer than anticipated. Finally got around to tidying up the tail-recursion stuff in the PP_EACH generator. Earlier implementation required std=gnu99, but now works with std=c99.

Closing out a release here, but will come back and rebase/resolve conflicts in the next couple of weeks.

cormacc avatar Jun 23 '19 16:06 cormacc

:x: Build fff 58-appveyor failed (commit https://github.com/meekrosoft/fff/commit/0e64cb5d00 by @)

AppVeyorBot avatar Jul 05 '19 10:07 AppVeyorBot

:x: Build fff 59-appveyor failed (commit https://github.com/meekrosoft/fff/commit/bbec0cdd77 by @)

AppVeyorBot avatar Jul 05 '19 11:07 AppVeyorBot

@wulfgarpro Finally got around to rebasing this etc. between a long flight delay a couple of weeks back and a slow test report export from Jira today :) Now works with std=c99 or std=gnu99 (though 0-counting case only works with gnu99 -- test included or excluded at compile time by sniffing for some gcc macros).

I think I've respected a recent change w.r.t. MSVCC calling conventions, but don't have access to a windows testbed to verify. Anyway, probably some more work to be done, but external feedback would be useful at this stage. I'll be away for the next week, but should have a bit of bandwidth after that.

cormacc avatar Jul 05 '19 11:07 cormacc

:x: Build fff 60-appveyor failed (commit https://github.com/meekrosoft/fff/commit/e7a2bb8ce7 by @)

AppVeyorBot avatar Jul 17 '19 22:07 AppVeyorBot

:x: Build fff 61-appveyor failed (commit https://github.com/meekrosoft/fff/commit/b80ecb0a73 by @)

AppVeyorBot avatar Jul 17 '19 22:07 AppVeyorBot

:x: Build fff 62-appveyor failed (commit https://github.com/meekrosoft/fff/commit/ad8b03f3c2 by @)

AppVeyorBot avatar Jul 17 '19 22:07 AppVeyorBot

:x: Build fff 63-appveyor failed (commit https://github.com/meekrosoft/fff/commit/1d0e52a385 by @)

AppVeyorBot avatar Jul 17 '19 22:07 AppVeyorBot

:x: Build fff 64-appveyor failed (commit https://github.com/meekrosoft/fff/commit/ac8742bc4e by @)

AppVeyorBot avatar Jul 17 '19 22:07 AppVeyorBot

:x: Build fff 65-appveyor failed (commit https://github.com/meekrosoft/fff/commit/c0a5fe8e0c by @)

AppVeyorBot avatar Jul 17 '19 23:07 AppVeyorBot

:x: Build fff 66-appveyor failed (commit https://github.com/meekrosoft/fff/commit/34044d90b6 by @)

AppVeyorBot avatar Jul 17 '19 23:07 AppVeyorBot

:white_check_mark: Build fff 67-appveyor completed (commit https://github.com/meekrosoft/fff/commit/ab343ed5f1 by @)

AppVeyorBot avatar Jul 17 '19 23:07 AppVeyorBot

:white_check_mark: Build fff 68-appveyor completed (commit https://github.com/meekrosoft/fff/commit/352f6fc73b by @)

AppVeyorBot avatar Jul 17 '19 23:07 AppVeyorBot

@wulfgarpro Worked through the obvious MSVC issues using your handy appveyor CI build. Initial issue was that appveyor uses ruby 1.9 by default -- set path in .appveyor.yml to use 2.0 instead. Also appears MSVC sticks to minimum VA_ARG support defined by standard (i.e. 127 args), which entailed limiting max countable args to 63. Then the lack of typeof() prevents using the variadic version of FFF_RETURN. And FFF_ASSERT_ANY / FFF_ASSERT_NONE require a GCC specific extension (statement expressions -- https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html). So have just #if guarded the associated tests and amended the README to indicate that these are GCC only.

It should be possible to get variadic FFF_RETURN to work with MSVC in C++ mode -- there's an #if there that uses typeof or decltype depending. But I'll leave that for someone who actually uses MSVC to follow up on.

Re. max countable/iterable args, could use dual #if guarded definitions for GCC and MSVC, s.t. the max for MSVC remains at 63, but max for GCC is 256?

UPDATE Added the new tests to the remaining test fixtures (was originally only in fff_test_c, now in _cpp, and _global variants too). Clearly still not ready -- issue seems to be with the parameterised iteration macros (PP_PAR_EACH). Working fine on GCC but not MSVC. Late now - will come back to it.

cormacc avatar Jul 17 '19 23:07 cormacc

:x: Build fff 69-appveyor failed (commit https://github.com/meekrosoft/fff/commit/e400f7253a by @)

AppVeyorBot avatar Jul 18 '19 00:07 AppVeyorBot

:x: Build fff 70-appveyor failed (commit https://github.com/meekrosoft/fff/commit/f8fa543867 by @)

AppVeyorBot avatar Jul 18 '19 00:07 AppVeyorBot

:x: Build fff 71-appveyor failed (commit https://github.com/meekrosoft/fff/commit/9f9a0decf8 by @)

AppVeyorBot avatar Jul 18 '19 01:07 AppVeyorBot

:x: Build fff 72-appveyor failed (commit https://github.com/meekrosoft/fff/commit/c0f9bd4a02 by @)

AppVeyorBot avatar Jul 18 '19 01:07 AppVeyorBot

:x: Build fff 73-appveyor failed (commit https://github.com/meekrosoft/fff/commit/4756ab2cb1 by @)

AppVeyorBot avatar Jul 18 '19 01:07 AppVeyorBot

:x: Build fff 74-appveyor failed (commit https://github.com/meekrosoft/fff/commit/ec7c1d46da by @)

AppVeyorBot avatar Jul 18 '19 01:07 AppVeyorBot