Googlemock can help build mock classes with which it is possible to detect if one method calls another method and with what parameters, and influence the behaviour of the called method.
E.g., to test that method a() in class UnderTest actually calls method b()
class UnderTest {
public:
/// Method a() calls method b().
virtual void a() {b();}
/// Method b() does nothing.
virtual void b() {}
};
one can write a mock class which overwrites method b()
class UnderTestMock : public UnderTest {
public:
MOCK_METHOD0(b, void());
};
and test if the method b() is actually called after calling method a():
TEST(UnderTest, aCallsB) {
UnderTestMock mock;
EXPECT_CALL(mock, b());
mock.a();
}
Can I use Googlemock like this with C++Builder 11.2?
No, at the moment it is not possible to use Googlemock like this with C++Builder 11.2.
The Googletest project (which includes Googlemock) itself has removed all support for C++Builder in 2019. Embarcadero has since published their own patched version of Googletest in a GetIt package, which includes project files to build Googletest and Googlemock and some usage examples.
The Googlemock-related project files are all somewhat broken, e.g. the gmock.cbproj file inserts a source file into the gmock.a library that performs some unrelated tests on Googletest. These project file errors can all be fixed easily by removing source files from the projects that do not belong there and rebuild.
However, after fixing the gmock.cbproj project file, it turns out that the main feature of Googlemock, the EXPECT_CALL() macro, is not supported by C++Builder 11.2:
This is a simple source file which puts the code pieces from the question together, adds a main function and the required includes:
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
class UnderTest {
public:
/// Method a() calls method b().
virtual void a() {b();}
/// Method b() does nothing.
virtual void b() {}
};
class UnderTestMock : public UnderTest {
public:
MOCK_METHOD0(b, void());
};
TEST(UnderTest, aCallsB) {
UnderTestMock mock;
EXPECT_CALL(mock, b());
mock.a();
}
This sample works fine with Googlemock with other compilers (at most, tchar, _tmain need to be replaced with char, main), however, with C++Builder, some required features are missing from either the compiler or from the C++ standard library. The error message when compiling with C++Builder's clang-based 64-bit compiler is
Build FAILED.
C:\Users\...\Documents\Embarcadero\Studio\22.0\CatalogRepository\GoogleTest-2021.09\googlemock\include\gmock/gmock-nice-strict.h(134,6): C++ warning : __declspec attribute 'empty_bases' is not supported
C:\Users\...\Documents\Embarcadero\Studio\22.0\CatalogRepository\GoogleTest-2021.09\googlemock\include\gmock/gmock-nice-strict.h(174,6): C++ warning : __declspec attribute 'empty_bases' is not supported
C:\Users\...\Documents\Embarcadero\Studio\22.0\CatalogRepository\GoogleTest-2021.09\googlemock\include\gmock/gmock-nice-strict.h(215,6): C++ warning : __declspec attribute 'empty_bases' is not supported
c:\program files (x86)\embarcadero\studio\22.0\include\dinkumware64\type_traits(2686,1): C++ error : no matching function for call to 'invoke'
c:\program files (x86)\embarcadero\studio\22.0\include\dinkumware64\functional(216,10): C++ error : > in instantiation of function template specialization 'std::_Invoke_ret<void, testing::internal::DoDefaultAction &>' requested here
c:\program files (x86)\embarcadero\studio\22.0\include\dinkumware64\functional(165,2): C++ error : > in instantiation of member function 'std::_Func_impl<testing::internal::DoDefaultAction, std::allocator<int>, void>::_Do_call' requested here
c:\program files (x86)\embarcadero\studio\22.0\include\dinkumware64\xmemory0(704,23): C++ error : > in instantiation of function template specialization 'std::_Func_impl<testing::internal::DoDefaultAction, std::allocator<int>, void>::_Func_impl<testing::internal::DoDefaultAction, const std::allocator<int> &>' requested here
c:\program files (x86)\embarcadero\studio\22.0\include\dinkumware64\xmemory0(845,6): C++ error : > in instantiation of function template specialization 'std::allocator<std::_Func_impl<testing::internal::DoDefaultAction, std::allocator<int>, void> >::construct<std::_Func_impl<testing::internal::DoDefaultAction, std::allocator<int>, void>, testing::internal::DoDefaultAction, const std::allocator<int> &>' requested here
c:\program files (x86)\embarcadero\studio\22.0\include\dinkumware64\xmemory0(994,13): C++ error : > in instantiation of function template specialization 'std::allocator_traits<std::allocator<std::_Func_impl<testing::internal::DoDefaultAction, std::allocator<int>, void> > >::construct<std::_Func_impl<testing::internal::DoDefaultAction, std::allocator<int>, void>, testing::internal::DoDefaultAction, const std::allocator<int> &>' requested here
c:\program files (x86)\embarcadero\studio\22.0\include\dinkumware64\functional(376,6): C++ error : > (skipping 6 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
C:\Users\...\Documents\Embarcadero\Studio\22.0\CatalogRepository\GoogleTest-2021.09\googlemock\include\gmock/gmock-actions.h(470,4): C++ error : > in instantiation of function template specialization 'testing::Action<void ()>::Init<testing::internal::DoDefaultAction>' requested here
C:\Users\...\Documents\Embarcadero\Studio\22.0\CatalogRepository\GoogleTest-2021.09\googlemock\include\gmock/gmock-spec-builders.h(909,8): C++ error : > in instantiation of function template specialization 'testing::Action<void ()>::Action<testing::internal::DoDefaultAction, void>' requested here
C:\Users\...\Documents\Embarcadero\Studio\22.0\CatalogRepository\GoogleTest-2021.09\googlemock\include\gmock/gmock-spec-builders.h(1629,12): C++ error : > in instantiation of member function 'testing::internal::TypedExpectation<void ()>::TypedExpectation' requested here
C:\Users\...\Documents\Embarcadero\Studio\22.0\CatalogRepository\GoogleTest-2021.09\googlemock\include\gmock/gmock-spec-builders.h(1284,29): C++ error : > in instantiation of member function 'testing::internal::FunctionMocker<void ()>::AddNewExpectation' requested here
C:\Users\...\Documents\Embarcadero\Studio\Projects\gmocktest\main.cpp(26,2): C++ error : > in instantiation of member function 'testing::internal::MockSpec<void ()>::InternalExpectedAt' requested here
c:\program files (x86)\embarcadero\studio\22.0\include\dinkumware64\type_traits(2664,6): C++ error : > candidate template ignored: substitution failure [with _Callable = testing::internal::DoDefaultAction &, _Types = <>]: no matching function for call to '_Call'
3 Warning(s)
13 Error(s)
The two example projects included in the GetIt package for Googlemock hint that some isolated aspects of Googlemock may be working, like at least one Googlemock matcher works inside the EXPECT_THAT() macro, but none of the examples compiled by the GetIt package make use of the main feature of Googlemock, the EXPECT_CALL() macro.
Related
I am new to C++ Builder. I am translating a Delphi project into C++. I have translated some of the Delphi code into C++ and it compiles fine in C++Builder, but I get an error:
Unresolved external ColorClasses::TColorList:: referenced from ...
when I use the TColorList constructor in my MainForm in this way:
ColorClasses::TColorList *cl;
cl = new ColorClasses::TColorList();
The TColorList constructor is defined as follows in file ColorClasses.cpp:
__fastcall ColorClasses::TColorList::TColorList() : TColorClass()
{
fcolor_list = new TList();
}
The TColorList class is declared as follows in file ColorClasses.h:
class DELPHICLASS TColorList;
class PASCALIMPLEMENTATION TColorList : public TColorClass
{
private:
TList* fcolor_list;
public:
__fastcall TColorList();
virtual __fastcall ~TColorList();
};
I have searched the StackOverflow site for similar questions relevant to C++Builder, but I can't find one specific to my problem.
The problem seems to resolve itself if I remove the keywords DELPHICLASS and PASCALIMPLEMENTATION.
I was updating earlier c code (opencv1.0) to opencv 4 . While i was changing and updating api's everything looked fine , however, at the end i got the error with the above mentioned file as follows,
/usr/local/include/opencv4/opencv2/core/cvstd_wrapper.hpp:45:40: Declaration of constexpr static data member 'check' requires an initializer
/usr/local/include/opencv4/opencv2/core/cvstd_wrapper.hpp:47:31: Constexpr can only be used in variable and function declarations
I am using LLVM 8.1 and uses libc++(LLVM C++ standard library with c++ 11 support) as c++ standard library.
Following is the part of the code that shows error in opencv.
struct has_parenthesis_operator
{
private:
template<typename T>
CV_CONSTEXPR std::true_type check(typename std::is_same<typename
std::decay<decltype(std::declval<T>().operator()(std::declval<Args> .
()...))>::type, Ret>::type*);
template<typename> static CV_CONSTEXPR std::false_type check(...);
typedef decltype(check<C>(0)) type;
public:
static CV_CONSTEXPR bool value = type::value;
};
I have a snippet of code which compiles in C++ Builder XE8 using the classic BCC compiler. However, in Rad Studio 10 Seattle using the Clang compiler I get the error
'no matching constructor found for initialization of TChoiceItem'
Here is the snippet of code which causes the error.
LISTITEM_BEGIN( sch_TYPE_Choice )
LISTITEM_DATA( sch_TYPE_Daily, "Daily" )
LISTITEM_DATA( sch_TYPE_Weekly, "Weekly" )
LISTITEM_DATA( sch_TYPE_Monthly, "Monthly" )
LISTITEM_END()
Here is the code which defines TChoiceItem
//------------------------------------------------------------------------------
#define LISTITEM_BEGIN( Name ) TChoiceItem Name[] = {
//------------------------------------------------------------------------------
#define INT_LISTITEM_BEGIN( Name ) TIntChoiceItem Name[] = {
//------------------------------------------------------------------------------
#define LISTITEM_DATA( XCode, XText ) { XCode, 0, (char*)XText, 0 },
#define LISTITEM_DATA_NC( XShortText, XText ) { 0, (char*)XShortText, (char*)XText, 0 },
#define LISTITEM_DATA_EX( XCode, XShortText, XText ) { XCode, (char*)XShortText, (char*)XText, 0 },
#define LISTITEM_DATA_EX2( XCode, XShortText, XText, XDesc ) { XCode, (char*)XShortText, (char*)XText, (char*)XDesc },
#define LISTITEM_END() LISTITEM_DATA(0,0) };
I am fairly new to C++ so I am not exactly sure what to call the above method of defining a class/method.
Is this some sort of dated language feature not supported by the Clang compiler? Is there a way to modify the code or definition so the compiler will accept it?
Edit:
I found the actual declaration of the TChoiceItem class.
class TChoiceItem : public TChoiceBase
{
public:
char Code;
char *ShortText;
char *Text;
char *Desc;
};
It does't appear to have any sort of standard constructor at all. But somehow, everything still compiles and works with the classic BCC compiler.
Edit 2:
I found this question which looks to be describing a similar issue. Could it be that I need to include some kind of compiler flag when compiling the code? If so can I add a flag somehow in the embarcadero project compiler settings?
Using a list of values in braces to initialize the individual members of a class or struct is known as aggregate initialization.
As explained on cppreference.com, aggregate initialization isn't permitted if the class has a base class (among other restrictions). TChoiceItem inherits from TChoiceBase, so aggregate initialization isn't allowed (and the "classic" bcc32 compiler shouldn't have allowed it).
You have a couple of choices:
First, you can change the code to not inherit from TChoiceBase.
Second, you can define a constructor:
TChoiceItem(char code, char *short_text, char *text, char *desc)
: Code(code), ShortText(short_text), Text(text), Desc(desc) {}
C++11's uniform initialization means that your macros' syntax doesn't have to change: instead of braces meaning a list of values for individual members, the braces will mean a list of parameters to the constructor, but the result will be the same.
I use a C library from Java through JNA and one function does not flush properly (since the output appear all at once on program end). I have tried Java side System.out.flush(); with no luck.
In brief, I would like to call C fflush(stdout) from Java. With JNA already there (thus would prefer if no additional library) and without C to write.
I am aware of JNA Library mapping as in this question but that seems overkill to me.
The JNA library wrapping way code is actually not so heavy (at least for the flush all behavior).
protected interface CLibrary extends Library
{
static CLibrary clib = (CLibrary) Native.loadLibrary ("c", CLibrary.class);
int fflush (Pointer stream);
}
/* ... */
CLibrary.clib.fflush (null);
JNA also offer late binding method and these oneliners will do what you want
NativeLibrary.getInstance ("c").getFunction ("fflush").invokeInt (new Object[]{0});
// even shorter
Function.getFunction ("c", "fflush").invokeInt (new Object[]{0});
The tedious part comes when you want to limit flushing to stdout. You have to deal with vendor-specific code (stdout is either defined as a macro expanding to an array, Amtel avr-libc, to a function call, Microsoft msvcrt, or a pointer in GNU libc).
For the libc, you might use (two lines for legibility)
Pointer stdout = NativeLibrary.getInstance ("c").getGlobalVariableAddress ("stdout").getPointer (0);
Function.getFunction ("c", "fflush").invokeInt (new Object[]{stdout});
Adding this answer for Win32 / Win64 users, complementing FabienAndre's for GNU libc.
Selectively flushing the stdout stream calling the system's c library's fflush method via jna is hard and cumbersome. As FabienAndre already mentioned, it is difficult to get a hold of the stdout macro definition. For msvcrt (the Win32 / Win64 C library) it is defined via a function call to __iob_func(); the latter returning a pointer to an array of FILE structures. At index 0 is stdin, index 1 is stdout and index 2 is stderr. So for flushing stdout you even need to know the size of the FILE structure, of course, it is different for Win32 and Win64 ...
The following example is tested under Win64 but ought to work under Win32. It was inspired by the thread JNA solutions to catch stdout/stderr of DLL.
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public class JnaTest {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("msvcrt" , CLibrary.class);
Pointer __iob_func();
void printf(String format, Object... args);
int fflush (Pointer stream);
}
public static void main(String[] args) {
int sizeOfFileStructure = Platform.is64Bit() ? 48 : 32;
Pointer stdout = CLibrary.INSTANCE.__iob_func().share(sizeOfFileStructure);
CLibrary.INSTANCE.printf("Hello, World\n");
CLibrary.INSTANCE.fflush(stdout);
}
}
I am attempting to use the HP APDK with C++ Builder in RAD Studio XE5. I need to derive a class PlatformServices (or any name of my choosing) from HP's base class SystemServices. Here is my header PlatformServices.h:
/***************************************************************************\
APDK Platform Services
\***************************************************************************/
#ifndef _H_PLATFORMSERVICES
#define _H_PLATFORMSERVICES
#include "header.h" // HP APDK General Header
// class SystemServices {
// };
class PlatformServices : public SystemServices {
~PlatformServices ();
PlatformServices ();
};
#endif
Compiled as-is, I get the error:
[bcc32 Error] PlatformServices.h(13): E2303 Type name expected
Full parser context
PlatformServices.cpp(5): #include PlatformServices.h
PlatformServices.h(13): class PlatformServices
But if I comment out the #include and uncomment the definition for an empty class named SystemServices, the code compiles without error.
I can preprocess the code as-is (in Project Manager, right click on PlatformServices and select Preprocess) and I can see that the #include defines a well formed SystemServices class.
I've also disabled pre-compiled headers.
This seems like a compiler error, but it's a poor workman who blames his tools. I just can't believe C++ Builder would choke on something this basic, yet I can't see what I'm doing wrong. Help!
P.S. I've posted the full code and project files at: https://www.dropbox.com/s/sn1377y59r3idtz/apdk.zip
SystemServices is declared in the apdk namespace, so you need to specify that in your code, either directly:
class PlatformServices : public apdk::SystemServices
Or with a using namespace statement:
using namespace apdk;
class PlatformServices : public SystemServices