Conditional Derivation for Unit Testing - c++

I'm writing unit tests that encapsulate a hardware driver (user space), the design pattern that I'm using is as follows:
class uio
{
virtual uint32_t readbit(...);
virtual bool writebit(...);
// other driver related functions
// ...
};
class uio_test : public uio
{
virtual uint32_t readbit(...) override { /* don't talk to hardware, send back test data */ }
virtual bool writebit(...) override { /* don't talk to hardware, write test data */ }
};
class spi : public uio
{
// spi related functions
};
class i2c : public uio
{
// i2c related functions
};
My questions is how to go about making spi and uio properly inherit from either uio OR uio_test depending on the module (real program vs gtest). I've looked at conditionals for example:
template<bool test>
class spi : public std::conditional<test, uio_test, uio>
and this would work in world where all objects were derived simply from the main.
/* main.cpp */
spi<false> s;
s.init();
s.writebit();
/* gtest_main.cpp */
spi<true> s;
ASSERT_TRUE(s.init());
ASSERT_EQ(/* read/write test bits, etc*/);
however the uio derived objects are used in other specialized classes throughout the program, and I cannot see a good way of conditional construction, for example:
class temperature_monitor
{
createBuses();
spi<???>* spictrl_;
};
/* perhaps derive test classes, easy since most high level objects are singletons */
temperature_monitor::createBuses()
{
if (testmode)
spictrl_ = new spi<true>;
else
spictrl_ = new spi<false>;
}
Hope that's clear as mud for everyone. I'll answer a few questions before they're asked:
Q. How about pre-processor conditionals?
A. No, if possible, never.
Q. Why are you writing unit tests for low level bit banging drivers like spi?
A. Why not, there's some internal logic going on, and I'd rather catch errors in a unit test than try and debug a stupid missing 0 for a day.

I think what you want is a strategy pattern. uio provides a non-virtual interface and a pointer to an implementation. You think have a virtual interface and provide either a normal or test instance of that to the uio object, rather than trying to insert inheritance in the middle. Using the strategy pattern even allows you to plug in additional implementations.

Related

How to test RDMA code without actual hardware?

I have C++ code which makes use of infiniband verbs for RDMA communication. I need to unit test this code, and thus, the function calls related to RDMA such as ibv_get_device_list() need to succeed without any actual hardware. From my understanding, I can do the following:
Create my own definition of each function to return the desired value, and link to this custom definition instead of infinband/verbs.h during testing. - Turning out to be very tedious
Create an interface and provide real and fake implementations of each function. The real one would simply call the infiniband verbs. - Can't do this as it would require too many changes to the original code
Use Soft-RoCE - I need to use the same machine as both the client and server, which I haven't been able to do
Would it be possible to use gmock to mock these functions? What other options can I consider?
Number 2 is the way to go. I'm going to challenge this statement:
Can't do this as it would require too many changes to the original code
If all goes well, your IDE has a "global search and replace" that can be used.
Let's fine the easiest way to abstract out your code with a minimal amount of disruptive changes:
Start by defining a class that simply wraps those C library function calls:
class RDMA
{
public:
virtual struct ibv_device **ibv_get_device_list(int *num_devices)
{
return ::ibv_get_device_list(num_devices);
}
virtual void ibv_free_device_list(struct ibv_device **list)
{
return ::ibv_free_device_list(list);
}
virtual uint64_t ibv_get_device_guid(struct ibv_device *device)
{
return ::ibv_get_device_guid(device);
}
};
Extend the above class with any other related calls you might need.
At global scope, declare an instance of the above class and a pointer to it:
RDMA g_product_code_rdma;
RDMA* g_ptrRMDA = &g_product_code_rdma;
Replace all your product code calls to the ibv functions to call through to the class via the global pointer. That is, change this:
ibv_free_device_list(&list);
to be invoked as:
g_ptrRMDA->ibv_free_device_list(&list);
Alternatively, you could declare helper functions:
ibv_device **global_ibv_get_device_list(int *num_devices)
{
return g_ptrRDMA->ibv_get_device_list(num_devices);
}
And then replace all your calls to use the new "global" version. A simple sed\awk script or just use your IDE to globally search and replace those function calls would be the easiest approach.
At this point, your product code functions the same as before.
in your unit tests, you simply declare a MockRDMA class that inherits from the RDMA class above.
class MockRDMA : public RDMA
{
public:
ibv_device **ibv_get_device_list(int *num_devices) override
{
// return a fake list of devices
}
virtual void ibv_free_device_list(struct ibv_device **list) override
{
return;
}
virtual uint64_t ibv_get_device_guid(struct ibv_device *device) override
{
return 0x012345678;
}
};
Then you just say this at the start of your unit tests:
MockRDMA mock;
g_ptrRDMA = &mock;
Example:
bool test_that_thing()
{
RDMA* original = g_ptrRDMA;
MockRDMA mock;
g_ptrRDMA = &mock;
// test code to validate the code that depends on those RDMA calls
// restore the RDMA class
g_ptrRDMA = original;
return result;
}
If you do decide to go for option 3 (SoftRoCE), it is certainly possible to have the client and server on the same host. You can try a Vagrant box I have created to make it easy to test SoftRoCE in a VM.

C++: implementing multiple instances of an interface or an optional interface in a class

I'm having trouble finding best practice information about what I believe should be a fairly common problem pattern.
I will start with a specific (software update related) example, because it makes the discussion more concrete, but the issue should be fairly generic.
Say that I have a software updater interface:
struct Software_updater {
virtual ~Software_updater() = default;
virtual void action1(const Input1& input1) = 0;
virtual void action2() = 0;
virtual bool action3(const Input2& input2) = 0;
virtual Data1 info1() = 0;
virtual Data2 info2() = 0;
// etc.
};
For my first implementation A, I am lucky, everything is straightforward.
class A_software_updater : public Software_updater {
// ...
};
A B_software_updater, however, is more complicated. Like in the A-case, it is connected to the target to update in a non-trivial manner and maintains a target connection state. But more importantly, it can update two images: the application image, and the boot loader image.
Liking what I have so far, I see no real reason to go for a refactoring, so I assume I can just build upon it. I come up with the following solution:
class B_software_updater {
public:
Software_updater& application_updater() { return application_updater_; }
Software_updater& boot_loader_updater() { return boot_loader_updater_; }
private:
class Application_updater : public Software_updater {
// ...
} application_updater_;
class Boot_loader_updater : public Software_updater {
// ...
} boot_loader_updater_;
};
I.e. I am returning non-const references to "interfaces to" member variables. Note that they cannot be const, since they mute state.
Request 1: I think the solution above is a clean one, but I would be happy to get some confirmation.
In fact, I have recently faced the issue of having to optionally provide an interface in a class, based on compile-time selection of a feature, and I believe the pattern above is a solution for that problem too:
struct Optional_interface {
virtual ~Optional_interface() = default;
virtual void action1(const Input1& input1) = 0;
virtual void action2() = 0;
virtual bool action3(const Input2& input2) = 0;
virtual Data1 info1() = 0;
virtual Data2 info2() = 0;
// etc.
};
class A_implementation {
public:
#ifdef OPTIONAL_FEATURE
Optional_interface& optional_interface() { return optional_implementation_; }
#endif
// ...
private:
#ifdef OPTIONAL_FEATURE
class Optional_implementation : public Optional_interface {
// ...
} optional_implementation_;
#endif
// ...
};
Request 2: I could not find a simple (as in: not unnecessarily complicated template-based) and clean way to express a compile-time optional inheritance at the A_implementation-level. Can you?
Better solution
Based on a comment from #ALX23z about invalidation of member variable reference upon move, I am now rejecting my initial solution (original post). That invalidation problem would not be an issue for my case, but I am in search of a generic pattern.
As usual, the solution is obvious once one has found it.
First a summary of my initial problem.
Say that I have a software updater interface (or any interface, this is just an example):
struct Software_updater {
virtual ~Software_updater() = default;
virtual void action1(const Input1& input1) = 0;
virtual void action2() = 0;
virtual bool action3(const Input2& input2) = 0;
virtual Data1 info1() = 0;
virtual Data2 info2() = 0;
// etc.
};
A B_software_updater can update two images: an application image, and a boot loader image. Therefore, it wants to provide two instances of the Software_updater interface.
A solution that is better than the one in my original post is to declare a B_application_updater and a B_boot_loader_updater, constructed from a B_software_updater&, outside of B_software_updater, and instantiated by client code.
class B_application_updater : public Software_updater {
B_application_updater(B_software_updater&);
// ...
};
class B_boot_loader_updater : public Software_updater {
B_application_updater(B_boot_loader_updater&);
// ...
};
It does have the drawback of forcing the client code to create three objects instead of only one, but I think that the cleanliness outweighs that drawback.
This will work for the optional interface too (see original post):
class A_optional_implementation : public Optional_interface {
A_optional_implementation(A_implementation&);
};
A_optional_implementation will be declared outside of A_implementation.
Applications that do not need that interface will simply not instantiate A_optional_implementation.
Additional thoughts
This is an application of the adapter design pattern!
Basically, what this answer comes down to:
An Interface class.
An Implementation class that does the job, but does not really care about the interface. It does not inherit Interface. The point of this is that Implementation could "do the job" corresponding to several interfaces, without the complexity and drawbacks of multiple inheritance (name conflicts, etc.). It could also do the job corresponding to several instances of the same interface (my case above).
An Interface_adapter class that takes an Implementation& parameter in its constructor. It inherits Interface, i.e. it effectively implements it, and that is its only purpose.
Taking a step back, I realize that this is simply an application of the adapter pattern (although Implementationin this case does not necessarily need to implement any externally defined interface - its interface is just its public member functions)!
An intermediate solution: leave the adapter classes inside the implementation class
In the solution above, I specify that the adapter classes are declared outside of the implementation classes. While this seems logical for the traditional adapter pattern case, for my case, I could just as well declare them inside the implementation class (like I did in the original post) and make them public. The client code would still have to create the implementation and adapter objects, but the adapter classes would belong to the implementation namespace, which would look nicer.

writing in arduino with Solid principles

I am a C programmer and I am new in cpp.for some understandable reason i want to write my program in S.O.L.I.D way
I want to write a program in c++ in Arduino with OOP.
there are classA , classB ,ClassC and classD.
classA have to get data from serial port and give an array of bytes
to classB.
ClassB do some process and give another array of bytes to classC
classC make this array into a defined format it to propper
output. e.g json
classD take this output and send it via mqtt
my problems are
how can I program classA that if I change SerialPort to SPI or other peripheral just by changing a parameter?(Objects or entities should be open for extension, but closed for modification)
how these class communicate with each other that if in future instead of json in classC I choose xml without modifying other class I can extend classC?
sorry for bad English If I am not clear ask in comment
Embedded programming and OOP are not the best friends, especially in a very limited system like Arduino. The answer to both questions in classic OOP is polymorphism (with virtual functions). You can create an interface for classA and implement getting data in different ways in every derived class.
class DataGatherer {
public:
virtual char* getData() = 0;
virtual ~IClassA () = default;
};
class SerialPortDataGatherer: public DataGatherer {
public:
char* getData() override {
//any code here
}
};
For less resource-expensive solution you can pretty easily do mapping of parameter to a function (e.g. with a simple switch-case statement), if the functions will have common format (like they return array of data or whatever you actually need)
enum DataSources {
SerialPort,
SPI
}
char* getDataFromSerialPort() {
// logic here
}
char* getDataFromSPI() {
// logic here
}
char* getData(DataSources source) {
switch(source) {
case SerialPort:
return getDataFromSerialPort();
case SPI:
return getDataFromSPI();
}
Note that the first version will likely require a switch-case at some point as well (where you make the decision which input type you should use).

How to write tests for classes relying on the operating system

I have written a class that enumerates over the operating system's physical displays, retrieving their information and capabilities. I actually would like to test that this class works appropriately and embrace (unit) tests in general.
However, I have no idea how I would go about testing this class. Leaving the implementation details aside, it's basically defined as so:
class VideoMode {
public:
int64 width;
int64 height;
std::vector<int64> frequencies;
}
class Display {
protected:
std::vector<VideoMode> modes_;
std::string display_name_;
std::string adapter_name_;
bool primary_;
public:
Display(char* osDevName, char* osAdapterDevName);
// typical getters
}
How would I go about testing something that is so deeply integrated and dependent on the OS, and the physically attached hardware. I understand that writing an unit test for a class like this is difficult, so what alternatives do I have?
You should unit-test your class, not the os/external library functions.
You may add a facade layer which allows to mock those method. (That layer would not be unit tested by your UTs).
Something like:
class IOsVideoModeRetriever
{
public:
virtual ~IOsVideoModeRetriever() = default;
virtual std::vector<VideoMode> RetrieveVideoModes(/*...*/) = 0;
// ...
};
// CLass with implementation of OS specific functions
class OsVideoModeRetriever : public IOsVideoModeRetriever
{
public:
std::vector<VideoMode> RetrieveVideoModes(/*...*/) override;
// ...
};
// Class for UT
class OsVideoModeRetrieverMock : public IOsVideoModeRetriever
{
public:
MOCK(RetrieveVideoModes(/*...*/)); // Mock according to your framework
// ...
};
And your other class use it something like:
class Foo
{
public:
explicit Foo(IOsVideoModeRetriever&);
private:
IOsVideoModeRetriever& mOsVideoModeRetriever; // Or use `shared_ptr`
// depending of life time guaranty
};
Now you can test Foo.
You indeed would have problems if the os specific functions doesn't behave as you expected (Format of result, limitation to handle, edge case, ...), that should be limited to implementation part and not the interface.
First step: don't unit test not the interface with the OS, but the rest of the code. There is some code there; not much, but some.
Create an even lower API that your nice C++ interface talks to; it mimics a C style API your OS probably provides, even if it is a C++ class.
Like
struct OSDisplayInterface {
virtual ~OSDisplayInterface() {}
virtual std::size_t GetDisplayName( char const* name, char const* adapter, char* name, std::size_t name_buf_len ) = 0;
virtual bool IsDisplayPrimary( char const* name, char const* adapter ) = 0;
virtual bool GetVideoModeCount( char const* name, char const* adapter, std::size_t* mode_count ) = 0;
struct video_mode {
int64 width, height, frequency;
};
virtual bool GetVideoMode( char const* name, char const* adapter, std::size_t n, video_mode* mode ) = 0;
};
Or something that matches your lower level API as directly as you can. The idea is that this code should only fail in the real case if the OS's API fails.
Then test your C++ code against that, with fake OS video mode sets.
If you want to go further, this is basically outside of unit tests, but you can test either the above "OS display interface" or directly test your class against the OS.
To do this, however, you'll need a bunch of different hardware configurations.
Start with a farm of test machines you can remote-deploy code to and get results back.
Deploy your code, isolated from the rest of your code base, to those machines.
Each machine has an identifier on it.
Build a machine-identifier to test-results table.
Test against that. Ensure that when run on system "bob37", you get the right set of resolutions and the like.
Then, when an OS upgrade hits and the API is deprecated, you get an immediate red flag. (Of course, you also get red flags when a new driver is patched that gives new frequencies)
Unit test harness looks up the machine identifier, runs your code, and confirms the test results match.
Automate the deployment of the code to said machines so you can run the test on dozens of hardware platforms on a code change.
This is at best at the border of "unit testing". But you could imagine being in the middle of porting the OS-interface code to a new OS, environment or hardware, and running into problems that this would catch.

Inheritance hierarchy vs. multiple inheritance (C++)

Well, I was thinking about a design decision for the past few days and since I still cannot favor one over the other I thought maybe someone else has an idea.
The situation is the following: I have a couple of different interface classes abstracting several communication devices. Since those devices differ in their nature they also differ in the interface and thus are not really related. Lets call them IFooDevice and IBarDevice. More device types may be added over time. The language is C++.
Since other components (called clients from now on) might want to use one or more of those devices, I decided to provide a DeviceManager class to handle access to all available devices at runtime. Since the number of device types might increase, I would like to treat all devices equally (from the managers point of view). However, clients will request a certain device type (or devices based on some properties).
I thought of two possible solutions:
The first would be some kind of interitance hierarchy. All devices would subclass a common interface IDevice which would provide the (virtual) methods necessary for management and device query (like getProperties(), hasProperties(), ...). The DeviceManager then has a collection of pointers to IDevice and at some point a cast from Base to Derived would be necessary - either with a template method in the manager or after the request on the client's side.
From a design point of view, I think it would be more elegant to seperate the concerns of managing a device and the interface of the specific device itself. Thus it would lead to two unrelated interfaces: IManagedDevice and e.g. IFooDevice. A real device would need to inherit from both in order to "be" of a specific device type and to be managaeble. The manager would only manage pointers to IManagedDevice. However, at some point there will be the need to cast between now unrelated classes (e.g. from IManagedDevice to IFooDevice) if a client wants to use a device provided by the manager.
Do I have to choose the lesser of two evils here? And if so which one would it be? Or do I miss something?
Edit:
About the "managing" part. The idea is to have library providing a variety of communication devices different (client) applications can use and share. Managing merely comes down to the storage of instances, methods for registering a new device and looking up a certain device. The responsibility for choosing the "right" device for the task is up to the client side because it knows best which requirements it puts on the communication. In order to reuse and thus share available devices (and by that I mean real instances and not just classes) I need a central access point to all available devices. I'm not too fond of the manager itself but it's the only thing I could come up to in that case.
I think the visitor pattern is a better choice for this.
I think what Tom suggested might be altered a bit to suit your needs:
class IManagedDevice
{
IDevice* myDevice;
/* Functions for managing devices... */
};
In this case IDevice is an empty interface that all devices inherit from. It gives no real benefit, just make the class hierarchy handling slightly more bearable.
Then, you can have then ask for the specific device (IFooDevice or IBarDevice), probably via some sort of device type ID.
If all you need is to have a common code to manage the devices, and then pass each device to the appropriate place I think you can get away with something like this:
class IDevice
{
virtual void Handle() = 0;
};
class IFooDevice : public IDevice
{
virtual void Handle()
{
this->doFoo();
}
virtual void doFoo() = 0;
}
class IBarDevice : public IDevice
{
virtual void Handle()
{
this->doBar();
}
virtual void doBar() = 0;
}
With the manager calling the Handle function.
I think I'd go for a simple solution of having a base class for Device that takes care of registering the device in the global device list and then static methods for looking them up. Something like:
struct Device
{
static Device *first; // Pointer to first available device
Device *prev, *next; // Links for the doubly-linked list of devices
Device() : prev(0), next(first)
{
if (next) next->prev = this;
first = this;
}
virtual ~Device()
{
if (next) next->prev = prev;
if (prev) prev->next = next; else first = next;
}
private:
// Taboo - the following are not implemented
Device(const Device&);
Device& operator=(const Device&);
};
Then you can just derive all devices from Device and them will be automatically placed in the global list on construction and removed from the global list on destruction.
All your clients will be able to visit the list of all devices by starting from Device::first and following device->next. By doing a dynamic_cast<NeededDeviceType*>(device) clients can check if the device is compatible with what they need.
Of course any method that is implemented in every device type (e.g. a description string, a locking method to ensure exclusive use by one client and the like) can be exported also at the Device level.
when communicating with devices I separated the the device and the communication manager completely.
I had a simple communication manager that was based on Boost.Asio. The interface was something like
/** An interface to basic communication with a decive.*/
class coms_manager
{
public:
virtual
~coms_manager();
/** Send a command. */
virtual
void
send(const std::string& cmd) = 0;
/** Receive a command.
* #param buffsize The number of bytes to receive.
* #param size_exactly True if exactly buffsize bytes are to be received. If false, then fewer bytes may be received.
*/
virtual
std::string
recv( const unsigned long& buffsize = 128,
const bool& size_exactly = false) = 0 ;
/** Timed receive command.
* #param buffsize The number of bytes to receive.
* #param seconds The number of seconds in the timeout.
* #param size_exactly True if exactly buffsize bytes are to be received. If false, then fewer bytes may be received.
*/
virtual
std::string
timed_recv( const unsigned long& buffsize = 128,
const double& seconds = 5,
const bool& size_exactly = false) = 0;
};
I then implemented this interface for tcp (ethernet) and serial communications.
class serial_manager : public coms_manager {};
class ethernet_manager : public coms_manager {};
Each of the devices then contained (or pointed to) (rather than inherited) a coms_manager object
For example:
class Oscilloscope
{
void send(const std::string& cmd)
{
m_ComsPtr->send(cmd);
}
private:
coms_manager* m_ComsPtr;
};
You can then swap around the communication method by changing what the pointer points to.
For me, this didn't make much sense (the Oscilloscope was EITHER attached via serial OR via ethernet and so I actually opted for
template<class Manager>
class Oscilloscope
{
void send(const std::string& cmd)
{
m_Coms.send(cmd);
}
private:
Manager m_Coms;
};
and I now use
Oscilloscope<serial_manager> O1(/dev/tty1); // the serial port
Oscilloscope<ethernet_manager> O2(10.0.0.10); //The ip address
which makes more sense.
As for your suggestion as to have a generic device interface. I started with that too, but then wasn't sure of its utility - I always wanted to know exactly what equipment I was sending a command to, I neither needed nor wanted to work through an abstract interface.
At a first glance, the first approach seems fine for me if all devices need to be managed and no other stuff can be done with an unknown device. The meta data for a general device (e.g. name, ...) would typically be the data one need for managing devices.
However, if you need to separate the interface between the management and the device functionality, you can use virtual inheritance.
IManagedDevice and IFooDevice are both interfaces of the same concrete device, so they both have a common virtual base IDevice.
Concretely (run code):
#include <cassert>
class IDevice {
public:
// must be polymorphic, a virtual destructor is a good idea
virtual ~IDevice() {}
};
class IManagedDevice : public virtual IDevice {
// management stuff
};
class IFooDevice : public virtual IDevice {
// foo stuff
};
class ConcreteDevice : public IFooDevice, public IManagedDevice {
// implementation stuff
};
int main() {
ConcreteDevice device;
IManagedDevice* managed_device = &device;
IFooDevice* foo_device = dynamic_cast<IFooDevice*>(managed_device);
assert(foo_device);
return 0;
}