Google Mock : Setting argument in EXPECT_CALL - c++

I am trying to set a class member function parameter value in Google Mock, but I get build errors and I simply don't understand what is going on. Would it be possible for someone to explain please.
The function prototype is:
virtual int recv( Socket socket
, char *buffer
, int bufferLength
, int flags ) = 0;
I am trying to test it using:
TEST_F( IPV4SocketTests, Read_SockErr_ok )
{
Mock_SocketAdaptor *adaptor = new Mock_SocketAdaptor;
char *rcvBuffer = "testingRcvWorks";
EXPECT_CALL( *adaptor, recv( testing::_, testing::_, testing::_, testing::_ ) )
.WillRepeatedly( testing::DoAll(
testing::SetArgPointee<1>( rcvBuffer ),
testing::Return( strlen( rcvBuffer ) ) ) );
The error I am getting is regarding conversion from std::get.

The problem is that rcvBuffer is a pointer. That is why you must dereference it when setting the pointee. Here is how your EXPECT_CALL should look:
EXPECT_CALL( *adaptor, recv( testing::_, testing::_, testing::_, testing::_ ) )
.WillRepeatedly( testing::DoAll(
testing::SetArgPointee<1>( *rcvBuffer ),
testing::Return( strlen( rcvBuffer ) ) ) );
EDIT:
This is the approach I've used in my projects to mock returning a char array through a pointer
used as argument. First, you need to create a custom action that will copy the contents of the
buffer (you cannot use SetArrayArgument in this case):
ACTION_TEMPLATE(SetArgNPointeeTo, HAS_1_TEMPLATE_PARAMS(unsigned, uIndex), AND_2_VALUE_PARAMS(pData, uiDataSize))
{
std::memcpy(std::get<uIndex>(args), pData, uiDataSize);
}
Then, in a test use it like this:
Mock_SocketAdaptor *adaptor = new Mock_SocketAdaptor;
char rcvBuffer[] = "testingRcvWorks";
size_t bufferSize = sizeof("testingRcvWorks");
EXPECT_CALL( *adaptor, recv( testing::_, testing::_, testing::_, testing::_ ) )
.WillRepeatedly( testing::DoAll(
SetArgNPointeeTo<0>(std::begin(rcvBuffer), bufferSize),
testing::Return( strlen( rcvBuffer ) ) ) );

Related

ImGui slowing down when using cpr

So I am trying to make a changelogs sort of thing
auto request = cpr::Post (
cpr::Url{ "http://leoservices.xyz/pchangelogs.php" }
);
auto response = request.text.c_str ( );
sprintf_s ( G->changelogsBuffer , "Changelogs: %s" , response );
ImGui::InputTextMultiline ( "##Change Logs" , G->changelogsBuffer , sizeof ( G->changelogsBuffer ) , ImVec2 ( ImGui::GetContentRegionAvail ( ).x - 10 , ImGui::GetContentRegionAvail ( ).y - 58 ) , ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoMarkEdited );
This is the current code but when I got to this tab it just starts laggin' is their something I am doing wrong?

Weird error on mysql_stmt_execute

I have a weird error when trying to execute mysql_stmt_execute.
The flow goes:
I get the list of the tables in my database I am connecting. (catalog, schema and name)
For every table I'm getting the list of foreign keys, fields and indexes.
Everything goes good until I hit the table named performance_schema.events_stages_summary_by_account_by_event_name.
I get the error: Identifier name "events_stages_summary_by_account_by_event_name" is too long. The weird thing is that the name is not an identifier - it is a parameter to the query and it is less than 64 characters which is the identifier limit.
Below is the relevant code:
std::wstring query3 = L"SELECT kcu.column_name, kcu.ordinal_position, kcu.referenced_table_schema, kcu.referenced_table_name, kcu.referenced_column_name, rc.update_rule, rc.delete_rule FROM information_schema.key_column_usage kcu, information_schema.referential_constraints rc WHERE kcu.constraint_name = rc.constraint_name AND kcu.table_catalog = ? AND kcu.table_schema = ? AND kcu.table_name = ?;";
char *catalog_name = row[0] ? row[0] : NULL;
char *schema_name = row[1] ? row[1] : NULL;
char *table_name = row[2] ? row[2] : NULL;
MYSQL_BIND params[3];
unsigned long str_length1, str_length2, str_length3;
str_length1 = strlen( catalog_name ) * 2;
str_length2 = strlen( schema_name ) * 2;
str_length3 = strlen( table_name ) * 2;
str_data1 = new char[str_length1], str_data2 = new char[str_length2], str_data3 = new char[str_length3];
memset( str_data1, '\0', str_length1 );
memset( str_data2, '\0', str_length2 );
memset( str_data3, '\0', str_length3 );
memset( params, 0, sizeof( params ) );
strncpy( str_data1, catalog_name, str_length1 );
strncpy( str_data2, schema_name, str_length2 );
strncpy( str_data3, table_name, str_length3 );
params[0].buffer_type = MYSQL_TYPE_STRING;
params[0].buffer = (char *) str_data1;
params[0].buffer_length = strlen( str_data1 );
params[0].is_null = 0;
params[0].length = &str_length1;
params[1].buffer_type = MYSQL_TYPE_STRING;
params[1].buffer = (char *) str_data2;
params[1].buffer_length = strlen( str_data2 );
params[1].is_null = 0;
params[1].length = &str_length2;
params[2].buffer_type = MYSQL_TYPE_STRING;
params[2].buffer = (char *) str_data3;
params[2].buffer_length = strlen( str_data3 );
params[2].is_null = 0;
params[2].length = &str_length3;
if( mysql_stmt_bind_param( res1, params ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errorMsg.push_back( err );
result = 1;
break;
}
else
{
prepare_meta_result = mysql_stmt_result_metadata( res1 );
if( !prepare_meta_result )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errorMsg.push_back( err );
result = 1;
break;
}
else
{
if( mysql_stmt_execute( res1 ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errorMsg.push_back( err );
result = 1;
break;
}
Could someone please shed some light on the error? I can probably try to skip this table but I'd prefer not to.
[EDIT]
mysql --version
mysql ver 14.14 Distrib 5.6.35, for Linux (x86+64) using Editine wrapper
[/EDIT]
Edit:
Seems that the code is indeed OK and the strncpy is OK. I mistakenly read that the allocation was twice the length of the string but the length was still only one length of the string.
The reason why you see that error is because you are using a string which is not null terminated. This is caused by the fact that strncpy does not null-terminate the string if it exceeds the given limit and the limit you use is the actual length of the string:
memset( str_data1, '\0', str_length1 );
strncpy( str_data1, catalog_name, str_length1 );
params[0].buffer_length = strlen( str_data1 );
A better way to do this would be to use either snprintf(3) that does null terminate the string or by using the std::string constructor that takes a const char* and a length as parameters.

Split parts of function calling

I am going to give the least extreme example I have: (Names/Identifiers are irrelevant)
session.TransmitUnsafe(
Details::Solve,
samplesCount,
pinnedInputData.GetDevicePointer( ),
Offset( pinnedOutputApproximationData.GetDevicePointer( ), outputIndex ),
Offset( SolutionData.get( ), SolutionIndices.at( outputIndex * SolutionSize ) ),
InputLength,
OutputLength,
samplesCount
);
I need to split it to something like this:
auto kernelCallingHeader = {
Details::Solve,
samplesCount
};
auto kernelArgumentsPointers = {
pinnedInputData.GetDevicePointer( ),
Offset( pinnedOutputApproximationData.GetDevicePointer( ), outputIndex ),
Offset( SolutionData.get( ), SolutionIndices.at( outputIndex * SolutionSize ) )
};
auto kernelArgumentsLengths = {
InputLength,
OutputLength,
samplesCount
};
session.TransmitUnsafe(
kernelCallingHeader...,
kernelArguments...,
kernelArgumentsLengths...
);
I can't change session.TransmitUnsafe's parameters at all, but I want to somehow structize the calling to that function. (Entirely for readability purposes)
NOTE: I used ... like expandation of variadic template function's arguments, because I am sure there's a fine way with it.
It won't harm even to have a few macros.

Need to convert cstring to byte* and need to pass it as an i/p argument in c++ functions

In SendCompressedString(),
*passing the compressed data string as an i/p argument.
*Tried printing the whole compressed data in a console window.Can able to print it in the console window....
*Now i need to convert that whole data to Byte * and sizeof that data as an i/p argument to SendBytes()
bool NetOutputBuffer_c::SendCompressedString ( std::string sStr )
{
std::cout.write(sStr.c_str(), sStr.size());
SendInt ( sStr.size() );
return SendBytes ( sStr.c_str(), sStr.size() );
}
In SendBytes(),
Tried to print the pBuf data but can able to print only 5% of data...
what shall i need to do inorder to print the whole data?
bool NetOutputBuffer_c::SendBytes ( const void * pBuf, int iLen )
{
BYTE * pMy = (BYTE*)pBuf;
printf("pMy is %s\n",pMy);
while ( iLen>0 && !m_bError )
{
int iLeft = m_iBufferSize - ( m_pBufferPtr-m_pBuffer );
printf("iLeft is %d\n",iLeft);
if ( iLen<=iLeft )
{
printf("iLen is %d\n",iLen);
memcpy ( m_pBufferPtr, pMy, iLen );
printf("m_pBuffer is %s\n",(char*)m_pBufferPtr);
m_pBufferPtr += iLen;
break;
}
ResizeIf ( iLen );
}
return !m_bError;
}
Requirement::
In SendCompressedString(),
*Need to convert the whole data into Byte * and send it as an i/p argument to SendBytes()
*In SendBytes(),need to print all the data...
*Can someone please help me to achieve this?
Why are you doing the memcpy in a loop? That looks wrong to me. Here is the memcpy reference:
http://www.cplusplus.com/reference/cstring/memcpy/
So you just need to specify a source and destination pointer (address) and what size to copy. So your code should be:
bool NetOutputBuffer_c::SendBytes ( const void * pBuf, int iLen )
{
BYTE * pMy = (BYTE*)pBuf;
memcpy ( m_pBufferPtr, pMy, iLen );
}

Memory Corruption Due to Copy Constructor/Deleting Array?

I have a struct called SFrame which contains many elements, notably 2 elements which are of type unsigned char*. I create a member variable of this struct in my class but I newly initialize it on each iteration in a function in my class (except for when a certain boolean is true). I do this in the following manner:
if (false == m_bRemainderNeedsProcessing)
{
// ... calls before and after the initialization are unimportant and not shown
m_sFrame = SFrame();
}
Then I pass m_sFrame to a function to assign some of its elements and then I need to assign an unsigned char array to my pszMessage variable in my struct.
m_sFrame.iMessageSize = m_sFrame.iPayloadLength;
m_sFrame.iOriginalMessageSize = m_sFrame.iPayloadLength;
m_sFrame.pszMessage = new unsigned char[m_sFrame.iPayloadLength + Constants::RSSL_DECODE_PADDING];
m_sFrame.pszOriginalMessage = new unsigned char[m_sFrame.iPayloadLength + Constants::RSSL_DECODE_PADDING];
These SFrame instances are stored in a vector of SFrames i.e.
std::vector<SFrame>;
I want to be able to reuse m_sFrame for each iteration but I have to ensure that if I am going to clear the contents of the SFrame, that when I store it inside the vector, the SFrame is copied into the vector without losing it's assigned values. For this I create a copy constructor for SFrame:
I have attached an image of part of the SFrame's copy constructor.
At the end of my function, I clear the memory in the pszMessage (and the pszOriginalMessage which is almost the same) by doing the following:
ClearMemory(m_sFrame.pszMessage);
Where the ClearMemory function does the following:
void CPCAPParser::ClearMemory(unsigned char *pszBuffer)
{
if(pszBuffer != NULL)
{
delete [] pszBuffer;
}
}
Thee problem is, this function seems to be deleting more than it should do.... because after many iterations, I get an unhandled exception: Access Violation...
I've attached a few images that might help convey what the problem is. Really need help with this :(, if anyone needs me to add more details let me know.
Thanks
http://imageshack.com/f/pduGDLGZp (Constants::RSSL_DECODE_PADDING has length 7 so there are 13 bytes in total which have been set - made evident at the start of the memory block).
http://imageshack.com/f/exRaaEmip - Where I am calling ClearMemory (the memory address is obviously still the same).
I would post more images but I don't have enough rep...
SFrame:
struct SFrame
{
int* ipTemp_int_ptr;
int* ipTemp_int_ptr_actual;
int* piTimestampPos;
int* piOffset;
int iIP_Header_Length;
int iTCP_Header_Length;
int iTCP_Source_Port;
int iTCP_Dest_Port;
long long uiSequenceNumber;
long long uiInitialSequenceNumber;
long long uiAckNumber;
int iIp_total_length;
int iActual_frame_length;
int iOriginal_frame_length;
int iCaptured_frame_length;
int iTotalPayloadLength;
int iTotalMsgLoad;
int iPayloadLength;
int iBytesComplete;
int iFragmentID;
int iRemainder;
int iMessageSize;
int iOriginalMessageSize;
long long iNextExpectedSequenceNum;
std::string strSourceAddress;
std::string strDestAddress;
std::string strTimestamp;
unsigned char* pszMessage;
unsigned char* pszOriginalMessage;
unsigned int uiClientID;
int iStartOfRemainder;
int iAccumulatedMsgLength;
SFrame() : ipTemp_int_ptr ( NULL ),
ipTemp_int_ptr_actual ( NULL ),
piTimestampPos ( NULL ),
piOffset ( NULL ),
pszMessage ( NULL ),
pszOriginalMessage ( NULL ),
iIP_Header_Length( 0 ),
iTCP_Header_Length ( 0 ),
iTCP_Source_Port ( 0 ),
iTCP_Dest_Port ( 0 ),
iIp_total_length ( 0 ),
iActual_frame_length ( 0 ),
iOriginal_frame_length ( 0 ),
iCaptured_frame_length ( 0 ),
uiSequenceNumber( 0 ),
uiInitialSequenceNumber ( 0 ),
uiAckNumber( 0 ),
iPayloadLength ( 0 ),
iNextExpectedSequenceNum ( 0 ),
uiClientID ( 0 ),
iMessageSize ( 0 ),
iOriginalMessageSize ( 0 ),
iFragmentID( 0 ),
iTotalPayloadLength( 0 ),
iBytesComplete( 0 ),
iAccumulatedMsgLength ( 0 ),
iRemainder ( 0 ),
iStartOfRemainder( 0 ),
iTotalMsgLoad ( 0 )
{
}
SFrame(const SFrame &c_rSrc)
{
*this = c_rSrc;
}
SFrame &SFrame::operator=(const SFrame &c_rSrc)
{
iIP_Header_Length = c_rSrc.iIP_Header_Length;
iTCP_Header_Length = c_rSrc.iTCP_Header_Length;
iTCP_Source_Port = c_rSrc.iTCP_Source_Port;
iTCP_Dest_Port = c_rSrc.iTCP_Dest_Port;
iIp_total_length = c_rSrc.iIp_total_length;
iActual_frame_length = c_rSrc.iActual_frame_length;
iOriginal_frame_length = c_rSrc.iOriginal_frame_length;
iCaptured_frame_length = c_rSrc.iCaptured_frame_length;
iPayloadLength = c_rSrc.iPayloadLength;
uiSequenceNumber = c_rSrc.uiSequenceNumber;
uiInitialSequenceNumber = c_rSrc.uiInitialSequenceNumber;
uiAckNumber = c_rSrc.uiAckNumber;
iNextExpectedSequenceNum = c_rSrc.iNextExpectedSequenceNum;
uiClientID = c_rSrc.uiClientID;
iFragmentID = c_rSrc.iFragmentID;
iMessageSize = c_rSrc.iMessageSize;
iOriginalMessageSize = c_rSrc.iOriginalMessageSize;
iTotalPayloadLength = c_rSrc.iTotalPayloadLength;
iBytesComplete = c_rSrc.iBytesComplete;
iAccumulatedMsgLength = c_rSrc.iAccumulatedMsgLength;
iRemainder = c_rSrc.iRemainder;
iStartOfRemainder = c_rSrc.iStartOfRemainder;
iTotalMsgLoad = c_rSrc.iTotalMsgLoad;
strSourceAddress = c_rSrc.strSourceAddress;
strDestAddress = c_rSrc.strDestAddress;
strTimestamp = c_rSrc.strTimestamp;
pszMessage = (c_rSrc.pszMessage == NULL) ? NULL : new unsigned char[c_rSrc.iMessageSize];
pszOriginalMessage = (c_rSrc.pszOriginalMessage == NULL) ? NULL : new unsigned char[c_rSrc.iOriginalMessageSize];
if(pszMessage != NULL)
{
memcpy(pszMessage, c_rSrc.pszMessage, c_rSrc.iMessageSize);
}
if(pszOriginalMessage != NULL)
{
memcpy(pszOriginalMessage, c_rSrc.pszOriginalMessage, c_rSrc.iOriginalMessageSize);
}
return *this;
}
~SFrame()
{
delete [] pszMessage;
delete [] pszOriginalMessage;
}
};
Your problem is that your SFrame struct is not safely asignable, yet you are placing instances of this in a std::vector that will make copies.
Either:
Add a working user-defined copy constructor and assignment operator to your SFrame struct or
Replace the pointer members with std::vector.
You have many members in your struct now. If you miss just one in your copy constructor, or your handling of allocated memory is faulty, you will have a broken copy. Since a vector<SFrame> will create copies, having broken copies is a no-go with vector<SFrame>.
So instead of this, here is the fix using option 2:
#include <vector>
struct SFrame
{
std::vector<int> ipTemp_int_ptr;
std::vector<int> ipTemp_int_ptr_actual;
std::vector<int> piTimestampPos;
std::vector<int> piOffset;
int iIP_Header_Length;
int iTCP_Header_Length;
int iTCP_Source_Port;
int iTCP_Dest_Port;
long long uiSequenceNumber;
long long uiInitialSequenceNumber;
long long uiAckNumber;
int iIp_total_length;
int iActual_frame_length;
int iOriginal_frame_length;
int iCaptured_frame_length;
int iTotalPayloadLength;
int iTotalMsgLoad;
int iPayloadLength;
int iBytesComplete;
int iFragmentID;
int iRemainder;
int iMessageSize;
int iOriginalMessageSize;
long long iNextExpectedSequenceNum;
std::string strSourceAddress;
std::string strDestAddress;
std::string strTimestamp;
std::vector<unsigned char> pszMessage;
std::vector<unsigned char> pszOriginalMessage;
unsigned int uiClientID;
int iStartOfRemainder;
int iAccumulatedMsgLength;
SFrame() :
iIP_Header_Length( 0 ),
iTCP_Header_Length ( 0 ),
iTCP_Source_Port ( 0 ),
iTCP_Dest_Port ( 0 ),
iIp_total_length ( 0 ),
iActual_frame_length ( 0 ),
iOriginal_frame_length ( 0 ),
iCaptured_frame_length ( 0 ),
uiSequenceNumber( 0 ),
uiInitialSequenceNumber ( 0 ),
uiAckNumber( 0 ),
iPayloadLength ( 0 ),
iNextExpectedSequenceNum ( 0 ),
uiClientID ( 0 ),
iMessageSize ( 0 ),
iOriginalMessageSize ( 0 ),
iFragmentID( 0 ),
iTotalPayloadLength( 0 ),
iBytesComplete( 0 ),
iAccumulatedMsgLength ( 0 ),
iRemainder ( 0 ),
iStartOfRemainder( 0 ),
iTotalMsgLoad ( 0 )
{
}
};
Note that the copy constructor and assignment operator (and destructor) are now gone, thus making the code a lot easier to handle, as well as not having a chance of missing any of the members during the copy. Instead we let the compiler generate the copy, and the compiler will always get every member copied.
Now, your code base that uses the struct has to be recompiled, and you will inevitably get compiler errors. However those errors are usually very easy to fix. Most will probably require you to
Remove the lines with delete [] somepointer; where somePointer is now a vector and
If passing a pointer to the beginning of the buffer, you pass &vector[0] or vector.data(), since a vector is basically a wrapper for new[]/delete[].
Going back to your original code, one issue with your assignment operator is that you failed to delete the previous memory allocated, thus you have a memory leak. Also, you didn't check for self-assignment, given the way you wrote the copy operations. However, this may not have been the only error, as we didn't see how you're using these SFrame instances.
Therefore it may be better to change to vector, fix the compiler errors, rebuild and test your app.