How can Cmocka test that my (void) callback function was called with the correct parameters? - cmocka

I am using Cmocka for unit test and that cannot be changed.
I am testing part of my software which invokes callback functions, if a value changes, indicating which data item changed and what the new value is.
The callback functions have this signature:
typedef void (* Value_changed_call_back) (int item_Id, int new_value);
For unit test, I want to register some callback functions and ensure that they are actually invoked, and that they receive the correct parameters.
I can use expect_int() in my mocks, to validate that they are invoked with the correct parameters.
But, I don't see how I can use will_return() since my call back functions are of type void (and that can't be changed).
How would I declare a mock callback function and verify that it is called with the correct parameters? Note that if the function is not called, then the test should fail.

I saw this post and thought about this in CMocka API.
You can use expect_function_call(func) to indicates which function should be called and function_called() in the callback to mark the function as called.
I'm not sure since how long this feature is available (but present in 1.1.5 version).
I answered to this question in case someone comes across this topic even if it's a 2016 ask.

I think the best way to do what you want is to create a stub for the callback and register that. Then inside the callback you set some global variable to a value. Then you would be able to assert that value that gets set in your stub function. This works so long as the assert and the callback are executed on the same thread to make sure that the assert is not a race condition.

Related

How to test a private function inside an RxSwift observer?

observable.subscribe(onNext: { _ in
somePrivateFunction()
})
What is the RxSwift way to test that when observable receives an event the somePrivateFunction actually gets called or not? Since the subscription and the function are in the same class I can't mock it.
You need to check if any logic is placed in a subscription that can block call of this function. If there is - it may be worth to extract it to a parameter (eg. filter) so that logic can be a part of stream itself.
I assume that observable (source) is injected/redirected from another component (if it's not, most probably it should be). To mock that signal you can use TestableObservable, you can read more here: http://adamborek.com/rxtests-rxactionsheet/
Last but not least - you need to identify what kind of action somePrivateFunction() does. If it's setting some external values - then you can test that outgoing connection from that function. If it sets some internal flags - you can test if value of that flag has changed.

check if a lua function is anonymous?

I register callback as event handler in my game, like this:
--register event handler
EventDispatcher:register("fire", mt.onPlayerFire, self)
--this is the event handler
mt:onPlayerFire()
print("play fire")
end
--unregister event handler
EventDispachter:unregister("fire", mt.onPlayerFire, self)
When the event handler is a function in module mt, it is fine to unregister it, because I can find the same function in mt to unregister it, but when I use this form:
EventDispatcher:register("fire", function() doSomething() end, nil)
I could not unregister the event handler, because it is anonymous, so I want to add some checks in my register function to prevent anonymous function as the event handler.
I have found the Proto struct in lua source code may be helpful, but I do not know what each piece means.
https://www.lua.org/source/5.3/lobject.h.html#Proto
I could not unregister the event handler, because it is anonymouse
Every function in Lua is anonymous value. So you can't unregister not because it is anonymous but because you didn't save any reference to it.
There is no way to detect inside of EventDispatcher:register() if the passed value (of function type) is also saved elsewhere. So if you really have multiple callbacks for the same event, and you want to unregister one specific callback, then you must have a way to identify that exact callback function.
That means you should either save the function value somewhere, so its own value could be used later as identifier for unregister(), as it is now, or return new callback's instance id, generated inside of register() when callback was added. Either way, there's something to be stored outside of EventDispatcher to identify exact callback.
This kind of avoids your question a bit, but it might solve your problem nonetheless.
When registering a new callback you could simply return some sort of identifying value, like an ID, a table or even the function itself. This could allow you to unregister it at a later moment.
local firehandler = EventDispatcher:register("fire", function() do('something') end)
-- Do some stuff here...
EventDispatcher:unregister(firehandler)
The downside is that you may have to change the way your event dispatcher keeps track of its registered events, but at worst this means implementing some linked list, and at best you can just use a Lua table to keep track of your handlers.
As for detecting anonymous functions, that's not really possible. Lua doesn't distinguish a function you define in-place from one stored in a variable; it's ultimately the same thing.
It might be possible by using the debug library, by comparing the file/line where a function is defined with the call stack, but that's just inviting bugs into your code and would probably be rather slow.

Avoiding use of global variables with specific callback mechanism in Lua

I want to use a Lua API which has specific callback functions when events occur, e.g. when an TCP package arrives. At first the function have to be registered but by the functions name as a string, see the sample code below
function __init__()
local dstport = 4681
local dstIP = "192.168.1.42"
-- register the callback function
register_tcp_handler('tcp_package_handler', dstIP, dstPort)
end
-- callback function
function tcp_package_handler(srcIP, srcPort, dstIP, dstPort, payload)
-- check the payload, or reset watchdog
end
It would be nice to have other variables in callback function provided by the callee, e.g. watchdog-timer or other objects.
The most simple way I could think of is to make the extravariables global, but it is the least elegant way I reckon. Closures would be helpful if I could pass the function directly, but i can not. I have to use the functions name as a string.
Considering this mechanics, is there a more elegant way to privide variables to the callback function without making them global?
EDIT: Using closures like this
function closure_tcp_package_handler(srcIP, srcPort, dstIP, dstPort, payload, packagecounter, timerobject)
function tcp_package_handler(srcIP, srcPort, dstIP, dstPort, payload)
-- do some stuff, change packagecounter, timerobject
end
return 'tcp_package_handler'
end
and use this function twice to register, e.g. with packagecounter1, timerobject1 and packagecounter2, timerobject2, only the last pair of parameters will be changed.
You're dealing with a callback infrastructure. In which case, your code is not the one invoking the handler. As such, there's no way to hide those parameters; if you can change them, so can someone else with access to the module providing the handler.
That doesn't mean that they have to be global, of course. You could make them members of a table. You could even provide setter functions to set the parameters, if you want to make sure that they only get certain parameters.
The simple form of this is as follows:
local handler_params = {}
function tcp_package_handler(srcIP, srcPort, dstIP, dstPort)
-- check `handler_params.payload`
end
--Make `handler_params` available for outside modification
How you do that last part is entirely up to you. You could have made it a global, but if this is in a module somewhere, it'd be better to make it a member of that module's table. And again, if you want to have some control over who gets to poke at it and how, you can use setter functions:
function tcp_handler_set_payload(payload)
handler_params.payload = payload
end

in unit test, set mocked value to an argument (pass-by-reference)

I have a method:
-(void)startTaskForResult:(long long*)result {
...
}
The function I want to unit test invoke above function:
-(void)doWork {
long long result = 0;
[self startTaskForResult:&result];
}
I am using OCMock library to do unit tests. In my test case, I want to set the result argument to an mocked value e.g. 100 without care about the actual implementation of -(void)startTaskForResult:(long long*)result.
I tried the following way:
-(void)testDoWork{
// try to set 100 to argument 'result'
OCMStub([classToTest startTaskForResult:[OCMArg setToValue:OCMOCK_VALUE((long long){100})]]);
// run the function, but it doesn't use mocked value 100 for argument 'result'
[classToTest doWork];
...
}
But, when I run my test, it does't use the mocked value 100 for argument result. What is the right way to set mocked value to argument in my case then?
Few points to answer your question:
Code for your problem:
- (void)testDoWork
{
id mock = OCMPartialMock(classToTest)
OCMStub([mock startTaskForResult:[OCMArg setToValue:OCMOCK_VALUE((long long){100})]]).andForwardToRealObject;
// set your expectation here
[classToTest doWork];
}
To solve your particular problem:
Your object should be partial mock
Your method should be stubbed (you did it)
Your stub should be forwarded to real object (i assume you need method startTaskForResult: implementation to be called)
However, you face the problems because you are using wrong approach to test;
There're 3 most common strategies to write unit tests:
Arrange-Act-Assert used to test methods
Given-When-Then used to test functions
Setup-Record-Verify used to test side effects. This usually requires mocking.
So:
If you want to test that startTaskForResult: returns particular value - you should call just that and expect return value (not your case, method return type is void)
If method changes the state of object - you should expect that state change, like property value or so
If calling of doWork has a side effect of calling startTaskForResult:, you should stub it and expect it's call, almost like i've written in code above. However (!!!), however you shouldn't expect things like this. This is not a kind of behaviour that has much sense to test, because it's internal class implementation details. One possible case, when both methods are public and it's explicitly stated in class contract, that one method should call another with some preliminary setup. In this case you expect method call with some state / arguments.
To have your application code testable, you require continuously refactoring your code. Some code is untestable, it's probably better to adopt application code rather then try to cover it with tests anyway. You lose the initial goal of tests - refactoring safety and low cost of making changes.

LoadOperation.Completed vs. callback in DomainContext.Load()

Using Silverlight 3 with RIA: What's the difference between the LoadOperation.Completed event and using a callback through the DomainContext.Load method? Both fire asynchronously and both provide access to the LoadOperation. When/why would I use one over the other?
Thanks :-)
There's no difference; the 2 options are offered for flexibility. Many times, the callback will suffice, but if you return the LoadOperation from a method, the caller could then choose to subscribe.
Note that even if the Load completes before you subscribe to the Completed event, your handler will still get called. We guarantee every subscriber to the event will be called.
Agreed that there is not difference in functionality. It's about coding style. If the work I have to do following completion of the query is simple, like binding data to a grid, I like the use the following syntax to inline the completed code, rather than defining a separate method.
context.Load<EntityType>(query).Completed += (lo, args) =>
{
myGrid.ItemsSource = ((LoadOperation) lo).Entities;
}
This has the cleanliness of synchronous code, but the code inside the braces will in fact be executed asynchronously.
Good luck!

Resources