Testing implementation over interface - c++

I'm starting with test coverage for my C++ project and it was oddness for me, that a lot of frameworks cannot create parametrized unit test.
For example I have interface:
class IBuffer {
public:
virtual void pushBytes(void *data, int length) = 0;
virtual int getSize() = 0;
};
And a few implementors :
class BufferImplOne{};
class BufferImplTwo{};
Now I want to check that pushing bytes to buffer will really increment its size:
TEST_CASE("example/test", "Test for any IBuffer implementor") {
IBuffer *buf = // ... {I want external parameter to be here}
REQUIRE( buf->getSize() == 0 );
int dataLength = 10;
int data[dataLength];
buf->pushBytes(data, dataLength * sizeof(int));
REQUIRE( buf->getSize() == dataLength * sizeof(int));
}
Now I'm gonna to test each implementation, and first thing I want to do - is to check if implementor meets interface tests. But I don't want to copypaste the same code twice, I just want to pass implementation as a parameter to interface test. How to deal with such problem?
I am using CATCH, but seems like other framework don't provide same functionality too.
Anyway I am newcomer in unit testing and maybe I misunderstood something basic?

Something like this:
void TestBuffer(IBuffer& buf)
{
REQUIRE( buf.getSize() == 0 );
int dataLength = 10;
int data[dataLength];
buf.pushBytes(data, dataLength * sizeof(int));
REQUIRE( buf.getSize() == dataLength * sizeof(int));
}
TEST_CASE("example/test", "Test for BufferImplOne implementor")
{
BufferImplOne one;
TestBuffer(one);
}
TEST_CASE("example/test", "Test for BufferImplTwo implementor")
{
BufferImplTwo two;
TestBuffer(two);
}

Well, it's bona fide polymorphism.
void test(IBuffer& ib) {
// ... your tests here ...
}
int main() {
BufferImplOne one;
test(one);
BufferImplTwo two;
test(two);
}
I don't quite see what a framework could provide...

Related

c/c++ get large size data like 180 array from another class in stm32

I have an 32-bit ARM Cortex M4 (the processor in Pixhawk) to write two classes, each one is one threading in Pixhawk codebase setting.
The first one is LidarScanner, which dealing with incoming serial data and generates "obstacle situation". The second one is Algorithm, which handle "obstacle situation" and take some planning strategy. Here are my solution right now, use the reference function LidarScanner::updateObstacle(uint8_t (&array)[181]) to update "obstacle situation" which is 181 size array.
LidarScanner.cpp:
class LidarScanner{
private:
struct{
bool available = false;
int AngleArr[181];
int RangeArr[181];
bool isObstacle[181] = {}; //1: unsafe; 0:safe;
}scan;
......
public:
LidarScanner();
//main function
void update()
{
while(hal.uartE->available()) //incoming serial data is available
{
decode_data(); //decode serial data into three kind data: Range, Angle and Period_flag
if(complete_scan()) //determine if the lidarscanner one period is completed
{
scan.available = false;
checkObstacle(); //check obstacle situation and store safety in isObstacle[181]
scan.available = true;
}
}
}
//for another API recall
void updateObstacle(uint8_t (&array)[181])
{
for(int i=0; i<=181; i++)
{
array[i]=scan.isObstacle[i];
}
}
//for another API recall
bool ScanAvailable() const { return scan.available; }
......
}
Algorithm.cpp:
class Algorithm{
private:
uint8_t Obatcle_Value[181] = {};
class LidarScanner& _lidarscanner;
......
public:
Algorithm(class LidarScanner& _lidarscanner);
//main funcation
void update()
{
if (hal.uartE->available() && _lidarscanner.ScanAvailable())
{
//Update obstacle situation into Algorithm phase and do more planning strategy
_lidarscanner.updateObstacle(Obatcle_Value);
}
}
......
}`
Usually, it works fine. But I want to improve the performances so that I want to know what's the most effective way to do that. thanks!!!!
The most efficient way to copy data is to use the DMA.
DMAx_Channelx->CNDTR = size;
DMAx_Channelx->CPAR = (uint32_t)&source;
DMAx_Channelx->CMAR = (uint32_t)&destination;
DMAx_Channelx->CCR = (0<<DMA_CCR_MSIZE_Pos) | (0<<DMA_CCR_PSIZE_Pos)
| DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_MEM2MEM ;
while(!(DMAx->ISR & DMA_ISR_TCIFx ));
AN4031 Using the DMA controller.

Removing duplication between similar functions in C and C++, in an EmPy template

Those #things are EmPy
C++
const char *
publish__#(spec.base_type.type)(void * untyped_data_writer, const void * untyped_message)
{
DataWriter * topic_writer = static_cast<DataWriter *>(untyped_data_writer);
const __ros_msg_type & ros_message = *(const __ros_msg_type *)untyped_message;
__dds_msg_type dds_message;
conversion_cpp(ros_message, dds_message);
#(__dds_msg_type_prefix)DataWriter * data_writer =
#(__dds_msg_type_prefix)DataWriter::_narrow(topic_writer);
DDS::ReturnCode_t status = data_writer->write(dds_message, DDS::HANDLE_NIL);
// some common switch statements in C and C++
}
}
C
static const char *
publish(void * data_writer, const void * cool_message)
{
if (!data_writer) {return "data writer handle is null";}
if (!cool_message) {return "ros message handle is null";}
DDS::DataWriter * topic_writer = static_cast<DDS::DataWriter *>(data_writer);
__dds_msg_type dds_message;
const char * err_msg = conversion_c(cool_message, &dds_message);
if (err_msg != 0) {return err_msg;}
#(__dds_msg_type_prefix)DataWriter * data_writer =
#(__dds_msg_type_prefix)DataWriter::_narrow(topic_writer);
DDS::ReturnCode_t status = data_writer->write(dds_message, DDS::HANDLE_NIL);
#[for field in spec.fields]#
#[if field.type.type == 'string']#
#[if field.type.is_array]#
{
#[if field.type.array_size]#
size_t size = #(field.type.array_size);
#[else]#
size_t size = dds_message.#(field.name)_.length();
#[end if]#
for (DDS::ULong i = 0; i < size; ++i) {
// This causes the DDS::String_mgr to release the given c string without freeing it.
dds_message.#(field.name)_[i]._retn();
}
}
#[else]#
// This causes the DDS::String_mgr to release the given c string without freeing it.
dds_message.#(field.name)_._retn();
#[end if]#
#[end if]#
#[end for]#
// some common switch statements in C and C++
}
}
This question is a bit specific to an open source project I am trying to contribute to, so I ll point to the exact functions I guess.
This is the original C method
and this is the C++ method
Do I need to use function pointers?
Another thing going on here is that the C package depends on the C++ package.
(Maybe this isn't good question or is a vague question, but I am not sure what to do as I am new to this codebase)

Create multiple Objects without multiple declarations

I am trying to do a routine Init_buffer (which create a new buffer to new a new client). So far I only discovered this way (in pseudo-code):
//Globally
BufferClass buffer1('some_random_size');
BufferClass buffer2('some_random_size');
BufferClass buffer3('some_random_size');
(...)
//Binary data (chunck) from Nodejs Server
void buffering_mem(char* chunk, int size_chunk, int close_file,
int client, int total_size) {
if(client == 0) {
buffer1.write(chunk,size_chunk);
}
else if(client == 1) {
buffer2.write(chunk, size_chunk);
}
(...)
}
Now I want to do the whole process without the repetition of code. Any ideas?
You could read up on how to use a std::vector.
Something a bit like this:
std::vector<BufferClass> buffers(3, BufferClass(1024));
void buffering_mem(char* chunk, int size_chunk, int close_file
, int client, int total_size)
{
if(client >= buffers.size())
throw std::range_error("out of range client: " + std::to_string(client));
buffers[client].write(chunk, size_chunk);
}

Create a function with unique function pointer in runtime

When calling WinAPI functions that take callbacks as arguments, there's usually a special parameter to pass some arbitrary data to the callback. In case there's no such thing (e.g. SetWinEventHook) the only way we can understand which of the API calls resulted in the call of the given callback is to have distinct callbacks. When we know all the cases in which the given API is called at compile-time, we can always create a class template with static method and instantiate it with different template arguments in different call sides. That's a hell of a work, and I don't like doing so.
How do I create callback functions at runtime so that they have different function pointers?
I saw a solution (sorry, in Russian) with runtime assembly generation, but it wasn't portable across x86/x64 archtectures.
You can use the closure API of libffi. It allows you to create trampolines each with a different address. I implemented a wrapping class here, though that's not finished yet (only supports int arguments and return type, you can specialize detail::type to support more than just int). A more heavyweight alternative is LLVM, though if you're dealing only with C types, libffi will do the job fine.
I've come up with this solution which should be portable (but I haven't tested it):
#define ID_PATTERN 0x11223344
#define SIZE_OF_BLUEPRINT 128 // needs to be adopted if uniqueCallbackBlueprint is complex...
typedef int (__cdecl * UNIQUE_CALLBACK)(int arg);
/* blueprint for unique callback function */
int uniqueCallbackBlueprint(int arg)
{
int id = ID_PATTERN;
printf("%x: Hello unique callback (arg=%d)...\n", id, arg);
return (id);
}
/* create a new unique callback */
UNIQUE_CALLBACK createUniqueCallback(int id)
{
UNIQUE_CALLBACK result = NULL;
char *pUniqueCallback;
char *pFunction;
int pattern = ID_PATTERN;
char *pPattern;
char *startOfId;
int i;
int patterns = 0;
pUniqueCallback = malloc(SIZE_OF_BLUEPRINT);
if (pUniqueCallback != NULL)
{
pFunction = (char *)uniqueCallbackBlueprint;
#if defined(_DEBUG)
pFunction += 0x256; // variable offset depending on debug information????
#endif /* _DEBUG */
memcpy(pUniqueCallback, pFunction, SIZE_OF_BLUEPRINT);
result = (UNIQUE_CALLBACK)pUniqueCallback;
/* replace ID_PATTERN with requested id */
pPattern = (char *)&pattern;
startOfId = NULL;
for (i = 0; i < SIZE_OF_BLUEPRINT; i++)
{
if (pUniqueCallback[i] == *pPattern)
{
if (pPattern == (char *)&pattern)
startOfId = &(pUniqueCallback[i]);
if (pPattern == ((char *)&pattern) + sizeof(int) - 1)
{
pPattern = (char *)&id;
for (i = 0; i < sizeof(int); i++)
{
*startOfId++ = *pPattern++;
}
patterns++;
break;
}
pPattern++;
}
else
{
pPattern = (char *)&pattern;
startOfId = NULL;
}
}
printf("%d pattern(s) replaced\n", patterns);
if (patterns == 0)
{
free(pUniqueCallback);
result = NULL;
}
}
return (result);
}
Usage is as follows:
int main(void)
{
UNIQUE_CALLBACK callback;
int id;
int i;
id = uniqueCallbackBlueprint(5);
printf(" -> id = %x\n", id);
callback = createUniqueCallback(0x4711);
if (callback != NULL)
{
id = callback(25);
printf(" -> id = %x\n", id);
}
id = uniqueCallbackBlueprint(15);
printf(" -> id = %x\n", id);
getch();
return (0);
}
I've noted an interresting behavior if compiling with debug information (Visual Studio). The address obtained by pFunction = (char *)uniqueCallbackBlueprint; is off by a variable number of bytes. The difference can be obtained using the debugger which displays the correct address. This offset changes from build to build and I assume it has something to do with the debug information? This is no problem for the release build. So maybe this should be put into a library which is build as "release".
Another thing to consider whould be byte alignment of pUniqueCallback which may be an issue. But an alignment of the beginning of the function to 64bit boundaries is not hard to add to this code.
Within pUniqueCallback you can implement anything you want (note to update SIZE_OF_BLUEPRINT so you don't miss the tail of your function). The function is compiled and the generated code is re-used during runtime. The initial value of id is replaced when creating the unique function so the blueprint function can process it.

linux to windows C++ byte array

I have to replicate the following Java functionality in C++ to get data from Linux to Windows. Is Winsock2 the best way to go?.
Also, any reference code to suggest?
TIA,
B
import java.nio.ByteBuffer;
public class MessageXdr {
private ByteBuffer buffer;
private int size;
// taille max corps de message
private static final int T_MAX_CORPS_MSG = 16384;
public MessageXdr() {
buffer = ByteBuffer.allocate(4 * T_MAX_CORPS_MSG);
size =0;
}
public MessageXdr(byte[] array)
{
ByteBuffer tmpBuffer = ByteBuffer.wrap(array);
buffer = tmpBuffer.asReadOnlyBuffer();
size = array.length;
}
public int getSize()
{
return size;
}
public int getPosition()
{
return buffer.position();
}
public byte[] getArray()
{
return buffer.array();
}
public void resetBuffer()
{
size = 0;
buffer.rewind();
}
public int readInt()
{
int retour = buffer.getInt();
return retour;
}
public long readUnsignedInt()
{
ByteBuffer tmp = ByteBuffer.allocate(8);
tmp.putInt(0);
tmp.putInt(buffer.getInt());
return tmp.getLong(0);
}
public float readFloat()
{
float retour = buffer.getFloat();
return retour;
}
public void writeInt(int v)
{
buffer.putInt(v);
size+=4;
}
public void writeFloat(float v)
{
buffer.putFloat(v);
size+=4;
}
}
If you are allowed to use the MFC classes (CSocket), it might be closer to the code you have in Java.
http://msdn.microsoft.com/en-us/library/wxzt95kb(VS.80).aspx
Otherwise, Winsock2 is fine (the MFC classes just use that in their implementation).
I haven't worked with it yet, but when it comes to marshalling more complex data structures i would look into boost for the serialization part.
For the actual data transmission, winsock2 is the basic socket api in windows, all other api's are built on it (well, don't know about Windows 7) .But again, looking into boost could provide you with something platform independent you don't have to figure out twice. But from my experience, sockets are complex beasts, so you will have to figure out a lot anyway...
And avoid the CSocket from MFC, that's the worst implementation ever. (Even if some say that they fixed some of it's misbehaviours, it's just not worth it.)
Strict byte arrays don't need any translation from linux to windows or other systems. If you are dealing with integers and floats however...
Personally I would use Poco::BinaryWriter and Poco::BinaryReader
http://pocoproject.org/docs/Poco.BinaryWriter.html
using namespace Poco;
using namespace std;
std::ofstream myFile("path", ios::in | ios::binary);
BinaryWriter writer(myFile, BIG_ENDIAN_BYTE_ORDER);
writer << 10.0f;
writer << 10000;
//etc etc
myFile.close();
Now to read
std::ifstream myFile("path", ios::in | ios::binary);
BinaryReader reader(myFile, BIG_ENDIAN_BYTE_ORDER);
int intVariable;
float floatVariable;
reader >> floatVariable;
reader >> intVariable;
//etc etc
myFile.close();