Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variadic macro extensions to the FFF #48

Open
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

cormacc
Copy link

@cormacc cormacc commented Apr 5, 2018

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

@rubiot
Copy link
Contributor

rubiot commented Apr 6, 2018

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

@meekrosoft
Copy link
Owner

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

@cormacc
Copy link
Author

cormacc commented Apr 6, 2018 via email

@cormacc
Copy link
Author

cormacc commented Apr 6, 2018

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

@cormacc
Copy link
Author

cormacc commented Apr 6, 2018

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 cormacc force-pushed the variadic_extensions branch 2 times, most recently from 6be4d1e to 1c488be Compare April 11, 2018 18:20
@cormacc
Copy link
Author

cormacc commented Apr 11, 2018

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 cormacc force-pushed the variadic_extensions branch 3 times, most recently from df8f5eb to d6d06fd Compare April 12, 2018 15:04
@meekrosoft
Copy link
Owner

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

@cormacc
Copy link
Author

cormacc commented Apr 13, 2018

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.

@wulfgarpro
Copy link
Collaborator

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

@wulfgarpro wulfgarpro self-assigned this Nov 23, 2018
@wulfgarpro wulfgarpro self-requested a review November 23, 2018 10:29
@cormacc
Copy link
Author

cormacc commented Nov 24, 2018

@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.

@wulfgarpro wulfgarpro added this to the Release v1.1 milestone Mar 2, 2019
@cormacc
Copy link
Author

cormacc commented Jun 23, 2019

... 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.

@AppVeyorBot
Copy link

Build fff 58-appveyor failed (commit 0e64cb5d00 by @)

@AppVeyorBot
Copy link

Build fff 59-appveyor failed (commit bbec0cdd77 by @)

@cormacc
Copy link
Author

cormacc commented Jul 5, 2019

@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.

@AppVeyorBot
Copy link

Build fff 60-appveyor failed (commit e7a2bb8ce7 by @)

@AppVeyorBot
Copy link

Build fff 61-appveyor failed (commit b80ecb0a73 by @)

@AppVeyorBot
Copy link

Build fff 75-appveyor failed (commit b8323ac511 by @)

@AppVeyorBot
Copy link

Build fff 76-appveyor failed (commit 2cb4fc75e8 by @)

@AppVeyorBot
Copy link

Build fff 77-appveyor failed (commit 7b488744c3 by @)

@AppVeyorBot
Copy link

Build fff 78-appveyor failed (commit 3782c44e3e by @)

@AppVeyorBot
Copy link

Build fff 79-appveyor failed (commit 12d4a5931c by @)

@cormacc
Copy link
Author

cormacc commented Jul 18, 2019

If at first you don't succeed -- give up :) I'm really beginning to hate MSVC.
Parking for now until I have time to setup a windows/MSVC environment to test in -- not getting enough info from the appveyor build to diagnose where the issues are.

@cormacc
Copy link
Author

cormacc commented Jul 18, 2019

@wulfgarpro See here:
https://devblogs.microsoft.com/cppblog/msvc-preprocessor-progress-towards-conformance/
that MS seem to be phasing in a more compliant preprocessor. Any leeway to use this? Even if not, I may try getting the build working using the new preprocessor and work back from that point or something (i.e. close a smaller gap first... gcc->new msvc->old msvc)

@meekrosoft meekrosoft force-pushed the master branch 2 times, most recently from b0792e6 to bdb7397 Compare August 4, 2022 08:23
Cormac Cannon added 14 commits August 5, 2022 17:14
See header comment in fff.h for details -- summary extracted below:

Return value macros:

SET_RETURN_VAL_SEQ(function_name, ...)
Accepts a raw list of appropriately typed values
SET_RETURN_VAL(function_name, value)
Provided for API consistency

Assertion macros:

TEST_ASSERT_CALLS(function_name, expected_call_count)

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

TEST_ASSERT_NOT_CALLED(function_name)
 No calls made to the function.

TEST_ASSERT_CALL(function_name, ...parameters)
 Only one call made to the function with the specified parameter values.

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

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

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

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

<<Amendment 1>>
Added unit tests.
Added TEST_ASSERT_CALL(...), as couldn't get optional parameter verification for
TEST_ASSERT_CALLED to work in c99 mode.

<<Amendment 2>>
Updated generator.
Function name changes for consistency.
Initial documentation updates.

<<Amendment 3>>
FFF_RETURN: Made array declaration static to allow use in a fixture setup method

<<Amendment 4>>
FFF_RETURN
Reverted static array declaration as it prevented some types of initialisation.
Reformulated macro to use dedicated struct member for single values while still
allowing macro invocation to be prefixed with `static` keyboard when used
outside the test body.
Previously generated for GCC or non GCC. Now using
if defined(__GNUCC__) && !defined(__STRICT_ANSI__)
instead.

This is only for the IS_EMPTY macro so far -- further work required
for NARG macros.
I.e. including if gcc extensions available
Also sniffing for MSVC and using decltype rather than typeof
@AppVeyorBot
Copy link

Build fff 128-appveyor failed (commit 41a8ae1504 by @)

Formatting had been garbled. No syntax change / changed type of verified
from into to bool...
@AppVeyorBot
Copy link

Build fff 130-appveyor failed (commit e883ccb399 by @cormacc)

Renamed IS_EMPTY macro to ISEMPTY to avoid a collision with Zephyr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants