Preferred way to simulate system calls
I like to test every branch, and I have a class that calls open/read/close. It uses a hardcoded filename ("/dev/urandom"). It is a template in a detail namespace. What's the "boost way" when it comes to mocking these system calls? Should I make protected methods that normally call open/read/close, then subclass in a test and override them with different logic to force error paths? - Jim
On 11/07/17 01:00, James E. King, III via Boost wrote:
I like to test every branch, and I have a class that calls open/read/close. It uses a hardcoded filename ("/dev/urandom"). It is a template in a detail namespace. What's the "boost way" when it comes to mocking these system calls? Should I make protected methods that normally call open/read/close, then subclass in a test and override them with different logic to force error paths?
I'm not aware of any mocking support in Boost. But I would be opposed if, for the sake of testing, you would mangle the code so that functionality or performance is affected. I.e. what you describe would require these methods to be virtual, which is absolutely useless and harmful in normal use. I guess, if you really want to test you're actually calling open/read/close, you could build a mocking library and use LD_PRELOAD to inject it into the test. Or you could implement those functions in the test itself, so that they are resolved to by the linker. Unfortunately, I'm afraid you will have to deal with platform-specific linker API to forward unrelated calls to the real open/read/close functions. I don't think it is necessary to do a this deep test though. If you can reasonably test that the generation works as expected (i.e. 10 calls return 10 different conforming UUIDs), that would be enough. If you can test the generator by replacing the random_device used in the test, that's great. Just don't add any unnecessary overhead for that and don't make it easy to use the test code in real code by accident.
A better way than virtual is to make the code you want to test into a
template that takes a class parameter that provides the functions you want
to mock. It's easy to make it testable while sacrificing no performance.
On Nov 6, 2017 14:57, "Andrey Semashev via Boost"
On 11/07/17 01:00, James E. King, III via Boost wrote:
I like to test every branch, and I have a class that calls open/read/close. It uses a hardcoded filename ("/dev/urandom"). It is a template in a detail namespace. What's the "boost way" when it comes to mocking these system calls? Should I make protected methods that normally call open/read/close, then subclass in a test and override them with different logic to force error paths?
I'm not aware of any mocking support in Boost. But I would be opposed if, for the sake of testing, you would mangle the code so that functionality or performance is affected. I.e. what you describe would require these methods to be virtual, which is absolutely useless and harmful in normal use.
I guess, if you really want to test you're actually calling open/read/close, you could build a mocking library and use LD_PRELOAD to inject it into the test. Or you could implement those functions in the test itself, so that they are resolved to by the linker. Unfortunately, I'm afraid you will have to deal with platform-specific linker API to forward unrelated calls to the real open/read/close functions.
I don't think it is necessary to do a this deep test though. If you can reasonably test that the generation works as expected (i.e. 10 calls return 10 different conforming UUIDs), that would be enough. If you can test the generator by replacing the random_device used in the test, that's great. Just don't add any unnecessary overhead for that and don't make it easy to use the test code in real code by accident.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost
participants (3)
-
Andrey Semashev
-
James E. King, III
-
Jonathan Biggar