-
Notifications
You must be signed in to change notification settings - Fork 20
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
Feature/async #20
base: main
Are you sure you want to change the base?
Feature/async #20
Conversation
Hi Thomas and thanks for the PR ! What is the motivation for those changes exactly ? |
The main motivation is to make formulating and checking of asynchronous calls easier. I started out using the construct proposed in the documentation, but it has the drawback that it's a lot more typing than doing something like this: MOCK_EXPECT(m1).async(milliseconds(100)).once().in(s).with(10).returns(false); The interesting part is also that you can easily specify timeout values for the calls. In my case I'm testing communication protocols and the timeout handling is a core part of the testing. As you can see I'm still fighting a bit to get the modifications I made based on the c++11 standard work on the older standards, but I'll get there soon. If your interested in the code, I'm willing to take time to adapt anything that doesn't fit ! |
{ | ||
if (timeout_) | ||
{ | ||
while (!invocation_->verify()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this blocking until all the expectations are fulfilled or time out ?
What happens for other objects expectations ? Won't they sometimes succeed when they should have timed out ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. This is the idea. This determine if the objects expectations are met before the time out occurs. If you write that a function is expected to be called twice, then the function would wait for the function to be called twice until the timeout occurs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this can only be used with one expectation because it will block on that expectation ? What if test mock object has two methods with two expectations ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It didn't have time to work on this earlier. But here is an answer: it also works. As proof you can look in the test_async.cpp file for a demonstration of this.
Every expectation can have a time out value associated with it. The delaying of the execution is done inside the expectation verification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant is this will pass whereas it should have failed
BOOST_FIXTURE_TEST_CASE( mock_object_asynchonous_call_expectation_in_sequence, mock_error_fixture )
{
#if defined(MOCK_ASYNC)
const mock_class m{};
MOCK_EXPECT( m.my_tag ).async(MOCK_THREAD_NAMESPACE::chrono::milliseconds(50)).once().with( "some parameter" );
MOCK_EXPECT( m.my_tag ).async(MOCK_THREAD_NAMESPACE::chrono::milliseconds(5)).once().with( "some parameter2" );
MOCK_THREAD_NAMESPACE::thread context([&](){
MOCK_THREAD_NAMESPACE::this_thread::sleep_for(MOCK_THREAD_NAMESPACE::chrono::milliseconds(10));
m.my_method("some parameter");
m.my_method("some parameter2");
});
mock::verify();
CHECK_CALLS( 2 );
context.join();
#endif
}
and this will fail whereas it should have succeeded
BOOST_FIXTURE_TEST_CASE( mock_object_asynchonous_call_expectation_in_sequence, mock_error_fixture )
{
#if defined(MOCK_ASYNC)
const mock_class m{};
MOCK_EXPECT( m.my_tag ).async(MOCK_THREAD_NAMESPACE::chrono::milliseconds(50)).once().with( "some parameter" );
MOCK_EXPECT( m.my_tag ).async(MOCK_THREAD_NAMESPACE::chrono::milliseconds(20)).once().with( "some parameter2" );
MOCK_THREAD_NAMESPACE::thread context([&](){
MOCK_THREAD_NAMESPACE::this_thread::sleep_for(MOCK_THREAD_NAMESPACE::chrono::milliseconds(10));
m.my_method("some parameter2");
MOCK_THREAD_NAMESPACE::this_thread::sleep_for(MOCK_THREAD_NAMESPACE::chrono::milliseconds(20));
m.my_method("some parameter");
});
mock::verify();
CHECK_CALLS( 2 );
context.join();
#endif
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well sorry, actually the second one will pass with the current implementation, I was already thinking that first testing the timeout before the expectation completion would not work either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I get your point. The difficulty is actually making clear which time reference point is taken for checking the async expectation. I'll try to come up with something.
I'm still struggling to see what a real world use case would look like, would it be something like
? |
Yes you got the idea. For algorithmic computations, the usefulness of the async construct is not very obvious. It makes much more sense for me, when you want to test communication protocol implementations. For example, if you are writing a client protocol which uses a heartbeat frame to check the link to the server is good, you can test the heartbeat regularity very easily with the construct. This actually one of the case I'm using it for currently. Does this make more sense to you ? |
df62e44
to
afffdb4
Compare
This branch adds support for asynchronous expectations.
I think the code is ok now, and ready for comments. If you are interested in this extension let me know I will also extend the documentation.