fork download
  1. // http://a...content-available-to-author-only...l.com/1950.html
  2.  
  3. #include <memory.h>
  4. #include <assert.h>
  5.  
  6.  
  7. template<typename M>
  8. class CMockObject
  9. {
  10.  
  11. #define DECL_TEN(hundreds, tens) \
  12.   FINAL_V_DECL(hundreds, tens, 0) \
  13.   FINAL_V_DECL(hundreds, tens, 1) \
  14.   FINAL_V_DECL(hundreds, tens, 2) \
  15.   FINAL_V_DECL(hundreds, tens, 3) \
  16.   FINAL_V_DECL(hundreds, tens, 4) \
  17.   FINAL_V_DECL(hundreds, tens, 5) \
  18.   FINAL_V_DECL(hundreds, tens, 6) \
  19.   FINAL_V_DECL(hundreds, tens, 7) \
  20.   FINAL_V_DECL(hundreds, tens, 8) \
  21.   FINAL_V_DECL(hundreds, tens, 9)
  22.  
  23. #define DECL_HUNDRED(hundreds)\
  24.   DECL_TEN(hundreds, 0) \
  25.   DECL_TEN(hundreds, 1) \
  26.   DECL_TEN(hundreds, 2) \
  27.   DECL_TEN(hundreds, 3) \
  28.   DECL_TEN(hundreds, 4) \
  29.   DECL_TEN(hundreds, 5) \
  30.   DECL_TEN(hundreds, 6) \
  31.   DECL_TEN(hundreds, 7) \
  32.   DECL_TEN(hundreds, 8) \
  33.   DECL_TEN(hundreds, 9)
  34.  
  35. #define DECL_RETRIEVER \
  36.   DECL_HUNDRED(0) \
  37.   DECL_HUNDRED(1) \
  38.   DECL_HUNDRED(2) \
  39.   DECL_HUNDRED(3) \
  40.   DECL_HUNDRED(4) \
  41.   DECL_HUNDRED(5) \
  42.   DECL_HUNDRED(6) \
  43.   DECL_HUNDRED(7) \
  44.   DECL_HUNDRED(8) \
  45.   DECL_HUNDRED(9)
  46.  
  47. #define FINAL_V_DECL(hundreds, tens, units) \
  48.   virtual int V##hundreds##tens##units() { return hundreds * 100 + tens * 10 + units; };
  49.  
  50. class CThisCallVtIdxRetriever
  51. {
  52. DECL_RETRIEVER
  53. };
  54.  
  55. #if defined(_WIN32) && !defined(_WIN64)
  56. #undef FINAL_V_DECL
  57. #define FINAL_V_DECL(hundreds, tens, units) \
  58.   virtual int __cdecl V##hundreds##tens##units() { return hundreds * 100 + tens * 10 + units; };
  59.  
  60. class CCdeclVtIdxRetriever
  61. {
  62. DECL_RETRIEVER
  63. };
  64.  
  65. #undef FINAL_V_DECL
  66. #define FINAL_V_DECL(hundreds, tens, units) \
  67.   virtual int __stdcall V##hundreds##tens##units() { return hundreds * 100 + tens * 10 + units; };
  68.  
  69. class CStdCallVtIdxRetriever
  70. {
  71. DECL_RETRIEVER
  72. };
  73.  
  74. #undef FINAL_V_DECL
  75. #define FINAL_V_DECL(hundreds, tens, units) \
  76.   virtual int __fastcall V##hundreds##tens##units() { return hundreds * 100 + tens * 10 + units; };
  77.  
  78. class CFastCallVtIdxRetriever
  79. {
  80. DECL_RETRIEVER
  81. };
  82. #endif
  83.  
  84. #undef DECL_RETRIEVER
  85. #undef DECL_HUNDRED
  86. #undef DECL_TEN
  87. #undef FINAL_V_DECL
  88.  
  89. protected:
  90. void** const m_ppVT;
  91.  
  92. CMockObject()
  93. : m_ppVT(new void*[1000])
  94. {
  95. memset(m_ppVT, 0, sizeof(void*) * 1000);
  96. static_cast<M*>(this)->ExecuteStructors(true);
  97. }
  98. ~CMockObject()
  99. {
  100. static_cast<M*>(this)->ExecuteStructors(false);
  101. delete[] m_ppVT;
  102. }
  103.  
  104. private:
  105. template <typename SRC_FUN, typename MOCK_FUN>
  106. void DoInstantiateThisCall(SRC_FUN pFun, MOCK_FUN pSubst)
  107. {
  108. int (CThisCallVtIdxRetriever::*pV)() = (int (CThisCallVtIdxRetriever::*)()) pFun;
  109. const int idx = (CThisCallVtIdxRetriever().*pV)();
  110. memcpy(m_ppVT + idx, &pSubst, sizeof(void*));
  111. }
  112. #if defined(_WIN32) && !defined(_WIN64)
  113. template <typename SRC_FUN, typename MOCK_FUN>
  114. void DoInstantiateCdecl(SRC_FUN pFun, MOCK_FUN pSubst)
  115. {
  116. int (__cdecl CCdeclVtIdxRetriever::*pV)() = (int (__cdecl CCdeclVtIdxRetriever::*)()) pFun;
  117. const int idx = (CCdeclVtIdxRetriever().*pV)();
  118. ((MOCK_FUN*) m_ppVT)[idx] = pSubst;
  119. }
  120. template <typename SRC_FUN, typename MOCK_FUN>
  121. void DoInstantiateStdCall(SRC_FUN pFun, MOCK_FUN pSubst)
  122. {
  123. int (__stdcall CStdCallVtIdxRetriever::*pV)() = (int (__stdcall CStdCallVtIdxRetriever::*)()) pFun;
  124. const int idx = (CStdCallVtIdxRetriever().*pV)();
  125. ((MOCK_FUN*) m_ppVT)[idx] = pSubst;
  126. }
  127. template <typename SRC_FUN, typename MOCK_FUN>
  128. void DoInstantiateFastCall(SRC_FUN pFun, MOCK_FUN pSubst)
  129. {
  130. int (__fastcall CFastCallVtIdxRetriever::*pV)() = (int (__fastcall CFastCallVtIdxRetriever::*)()) pFun;
  131. const int idx = (CFastCallVtIdxRetriever().*pV)();
  132. ((MOCK_FUN*) m_ppVT)[idx] = pSubst;
  133. }
  134. #endif
  135.  
  136. protected:
  137.  
  138. #define PARAMS_MACRO_1(macro) macro(1)
  139. #define PARAMS_MACRO_2(macro) PARAMS_MACRO_1(macro), macro(2)
  140. #define PARAMS_MACRO_3(macro) PARAMS_MACRO_2(macro), macro(3)
  141. #define PARAMS_MACRO_4(macro) PARAMS_MACRO_3(macro), macro(4)
  142. #define PARAMS_MACRO_5(macro) PARAMS_MACRO_4(macro), macro(5)
  143. #define PARAMS_MACRO_6(macro) PARAMS_MACRO_5(macro), macro(6)
  144. #define PARAMS_MACRO_7(macro) PARAMS_MACRO_6(macro), macro(7)
  145. #define PARAMS_MACRO_8(macro) PARAMS_MACRO_7(macro), macro(8)
  146. #define PARAMS_MACRO_9(macro) PARAMS_MACRO_8(macro), macro(9)
  147.  
  148.  
  149. #define ARGS_MACRO_TEMPL(v) typename P##v
  150. #define ARGS_MACRO_DECL(v) P##v
  151.  
  152. #define DO_INVOKE_PARAMS_MACRO(macro, convention, modifier, varargs0, DoInstantiate, Instantiate, ...) \
  153.   template<macro(ARGS_MACRO_TEMPL), typename R, typename SRC, typename MOCK> \
  154.   void Instantiate(R (convention SRC::*pFun)(macro(ARGS_MACRO_DECL) __VA_ARGS__) modifier \
  155.   , R (convention MOCK::*pSubst)(macro(ARGS_MACRO_DECL) __VA_ARGS__) modifier) \
  156.   { \
  157.   DoInstantiate(pFun, pSubst); \
  158.   }
  159.  
  160. #define DO_DECL_INSTANTIATE_NO_PARAMS(convention, modifier, varargs0, DoInstantiate, Instantiate, ...) \
  161.   template<typename R, typename SRC, typename MOCK> \
  162.   void Instantiate(R (convention SRC::*pFun)(varargs0) modifier \
  163.   , R (convention MOCK::*pSubst)(varargs0) modifier) \
  164.   { \
  165.   DoInstantiate(pFun, pSubst); \
  166.   }
  167.  
  168. #define DECL_EMPTY
  169. #define DECL_VARARGS_0 ...
  170. #define DECL_VARARGS_X , ...
  171.  
  172. #define DECL_INSTANTIATE_NO_PARAMS(args) DO_DECL_INSTANTIATE_NO_PARAMS args
  173. #define INVOKE_PARAMS_MACRO(args) DO_INVOKE_PARAMS_MACRO args
  174.  
  175. #define DECL_INSTANTIATE(...) \
  176.   DECL_INSTANTIATE_NO_PARAMS((__VA_ARGS__)) \
  177.   INVOKE_PARAMS_MACRO((PARAMS_MACRO_1, __VA_ARGS__)) \
  178.   INVOKE_PARAMS_MACRO((PARAMS_MACRO_2, __VA_ARGS__)) \
  179.   INVOKE_PARAMS_MACRO((PARAMS_MACRO_3, __VA_ARGS__)) \
  180.   INVOKE_PARAMS_MACRO((PARAMS_MACRO_4, __VA_ARGS__)) \
  181.   INVOKE_PARAMS_MACRO((PARAMS_MACRO_5, __VA_ARGS__)) \
  182.   INVOKE_PARAMS_MACRO((PARAMS_MACRO_6, __VA_ARGS__)) \
  183.   INVOKE_PARAMS_MACRO((PARAMS_MACRO_7, __VA_ARGS__)) \
  184.   INVOKE_PARAMS_MACRO((PARAMS_MACRO_8, __VA_ARGS__)) \
  185.   INVOKE_PARAMS_MACRO((PARAMS_MACRO_9, __VA_ARGS__))
  186.  
  187. #define DECL_INSTANTIATE_CONVENTION(convention, CustomInstantiate) \
  188.   DECL_INSTANTIATE(DECL_EMPTY convention, DECL_EMPTY, DECL_EMPTY, CustomInstantiate, Instantiate, DECL_EMPTY) \
  189.   DECL_INSTANTIATE(DECL_EMPTY convention, const, DECL_EMPTY, CustomInstantiate, Instantiate, DECL_EMPTY)
  190.  
  191. DECL_INSTANTIATE_CONVENTION(DECL_EMPTY, DoInstantiateThisCall)
  192. #if defined(_WIN32) && !defined(_WIN64)
  193. DECL_INSTANTIATE_CONVENTION(__cdecl, DoInstantiateCdecl)
  194. DECL_INSTANTIATE_CONVENTION(__stdcall, DoInstantiateStdCall)
  195. DECL_INSTANTIATE_CONVENTION(__fastcall, DoInstantiateFastCall)
  196. #endif
  197.  
  198. #if defined(_WIN32) && !defined(_WIN64)
  199. DECL_INSTANTIATE(__cdecl, DECL_EMPTY, DECL_VARARGS_0, DoInstantiateCdecl, InstantiateVA, DECL_VARARGS_X)
  200. DECL_INSTANTIATE(__cdecl, const, DECL_VARARGS_0, DoInstantiateCdecl, InstantiateVA, DECL_VARARGS_X)
  201. #else
  202. DECL_INSTANTIATE(DECL_EMPTY, DECL_EMPTY,DECL_VARARGS_0, DoInstantiateThisCall, InstantiateVA, DECL_VARARGS_X)
  203. DECL_INSTANTIATE(DECL_EMPTY, const, DECL_VARARGS_0, DoInstantiateThisCall, InstantiateVA, DECL_VARARGS_X)
  204. #endif
  205.  
  206. #undef INVOKE_PARAMS_MACRO
  207.  
  208. #undef ARGS_MACRO_TEMPL
  209. #undef ARGS_MACRO_DECL
  210.  
  211. #undef PARAMS_MACRO_1
  212. #undef PARAMS_MACRO_2
  213. #undef PARAMS_MACRO_3
  214. #undef PARAMS_MACRO_4
  215. #undef PARAMS_MACRO_5
  216. #undef PARAMS_MACRO_6
  217. #undef PARAMS_MACRO_7
  218. #undef PARAMS_MACRO_8
  219. #undef PARAMS_MACRO_9
  220.  
  221.  
  222. #undef DECL_INSTANTIATE
  223. #undef DECL_EMPTY
  224. #undef DECL_VARARGS_0
  225. #undef DECL_VARARGS_X
  226.  
  227.  
  228. template<typename T, typename C> void ExecuteStructor(T C::*r, bool construct)
  229. {
  230. C* other = (C*) this;
  231.  
  232. if (construct)
  233. {
  234. ::new(&((*other).*r)) T();
  235. }
  236. else
  237. {
  238. ((*other).*r).~T();
  239. }
  240. }
  241. };
  242.  
  243.  
  244.  
  245. #define DECLARE_MOCK_MEMBERS(src, mock) \
  246. public: \
  247.   typedef src TMockOrigin; \
  248.   char m_membersAllocBuffer[sizeof(src)]; \
  249. public: \
  250.   void ExecuteStructors(bool construct) \
  251.   { \
  252.   int iMemberCountN = -1; \
  253.   EnumerateStructors(iMemberCountN, construct); \
  254.   iMemberCountN = ~iMemberCountN; \
  255.   if (construct) \
  256.   { \
  257.   int i = 0; \
  258.   try \
  259.   { \
  260.   for (; i < iMemberCountN; ++i) \
  261.   { \
  262.   ExecuteNthStructor(i, construct); \
  263.   } \
  264.   } \
  265.   catch (...) \
  266.   { \
  267.   for (; i >= 0; --i) \
  268.   { \
  269.   ExecuteNthStructor(i, false); \
  270.   } \
  271.   throw; \
  272.   } \
  273.   } \
  274.   else \
  275.   for (int i = iMemberCountN; --i >= 0; ) \
  276.   { \
  277.   ExecuteNthStructor(i, construct); \
  278.   } \
  279.   } \
  280.   void ExecuteNthStructor(int iMemberToCall, bool construct) \
  281.   { \
  282.   EnumerateStructors(iMemberToCall, construct); \
  283.   assert(0 == iMemberToCall); \
  284.   } \
  285.   void EnumerateStructors(int& iMemberToCall, bool construct)
  286.  
  287.  
  288. // It is not necessary to declare POD types
  289. #define DECLARE_MOCK_MEMBER(member) \
  290.   if (0 == iMemberToCall) \
  291.   { \
  292.   ExecuteStructor(&TMockOrigin::member, construct); \
  293.   return; \
  294.   } \
  295.   --iMemberToCall;
  296.  
  297. // That's an example of its usage:
  298. // #include "MockObject.h"
  299. #include <iostream>
  300. #include <sstream>
  301.  
  302. using std::string;
  303. using std::ostringstream;
  304. using std::cerr;
  305.  
  306. class A
  307. {
  308. public:
  309. virtual string Dummy0(int*);
  310.  
  311. virtual string Dummy0(int) const;
  312.  
  313. virtual void Dummy2(const char*);
  314.  
  315. virtual int Dummy3();
  316. virtual int Dummy3Const() const;
  317.  
  318. virtual string SomeOtherTest(int i, int& j);
  319.  
  320. virtual int TakeThree(int i, int j, int k);
  321.  
  322. virtual int TakeFour(int i, int j, int k, int l);
  323.  
  324. virtual int TakeThreeConst(int i, int j, int k) const;
  325.  
  326. virtual int TakeFourConst(int i, int j, int k, int l) const;
  327.  
  328. virtual int TakeFive(int i, int j, int k, int l, int m);
  329. virtual int TakeFiveConst(int i, int j, int k, int l, int m) const;
  330.  
  331. virtual double TakeFive2(int i, int j, int k, int l, int m);
  332.  
  333. virtual double Test2ThisCall(int i, int& j);
  334.  
  335. #if defined(_WIN32)
  336. virtual void __stdcall StdCall(char*);
  337. virtual double __cdecl Test2Cdecl(int i, int& j);
  338. virtual double __stdcall Test2StdCall(int i, int& j);
  339. virtual double __fastcall Test2FastCall(int i, int& j);
  340. #endif
  341.  
  342. virtual double TestVarArgsThisCall(int i, ...);
  343.  
  344. virtual double TestVarArgs0ThisCall(...);
  345.  
  346. int dummy;
  347.  
  348. string buffer2;
  349.  
  350. int dummy2;
  351.  
  352. string buffer;
  353. };
  354.  
  355. class CXTest : public CMockObject<CXTest>
  356. {
  357. public:
  358.  
  359. CXTest()
  360. {
  361. Instantiate(static_cast<string (A::*)(int) const>(&A::Dummy0), &CXTest::DoTest);
  362. Instantiate(static_cast<string (A::*)(int*)>(&A::Dummy0), &CXTest::DoAnotherTest);
  363. Instantiate(&A::Dummy2, &CXTest::YetAnotherTest);
  364.  
  365. Instantiate(&A::Dummy3, &CXTest::NoParamsTest);
  366. Instantiate(&A::Dummy3Const, &CXTest::NoParamsTestConst);
  367. Instantiate(&A::TakeThree, &CXTest::TakeThree);
  368. Instantiate(&A::TakeFour, &CXTest::TakeFour);
  369. Instantiate(&A::TakeThreeConst, &CXTest::TakeThreeConst);
  370. Instantiate(&A::TakeFourConst, &CXTest::TakeFourConst);
  371. Instantiate(&A::TakeFive, &CXTest::TakeFive);
  372. Instantiate(&A::TakeFive2, &CXTest::TakeFive2);
  373. Instantiate(&A::TakeFiveConst, &CXTest::TakeFiveConst);
  374.  
  375. Instantiate(&A::SomeOtherTest, &CXTest::SomeOtherTest);
  376.  
  377. Instantiate(&A::Test2ThisCall, &CXTest::Test2ThisCall);
  378. #if defined(_WIN32)
  379. Instantiate(&A::StdCall, &CXTest::StdCall);
  380. Instantiate(&A::Test2Cdecl, &CXTest::Test2Cdecl);
  381. Instantiate(&A::Test2StdCall, &CXTest::Test2StdCall);
  382. Instantiate(&A::Test2FastCall, &CXTest::Test2FastCall);
  383. #endif
  384.  
  385. InstantiateVA(&A::TestVarArgsThisCall, &CXTest::TestVarArgsThisCall);
  386. InstantiateVA(&A::TestVarArgs0ThisCall, &CXTest::TestVarArgs0ThisCall);
  387. }
  388.  
  389. DECLARE_MOCK_MEMBERS(A, CXTest)
  390. {
  391. DECLARE_MOCK_MEMBER(buffer)
  392. DECLARE_MOCK_MEMBER(buffer2)
  393. }
  394.  
  395. string DoTest(int i) const
  396. {
  397. ostringstream s;
  398. s << i;
  399. return s.str();
  400. }
  401.  
  402. string DoAnotherTest(int* i)
  403. {
  404. ostringstream s;
  405. s << -*i;
  406. return s.str();
  407. }
  408.  
  409. void YetAnotherTest(const char* p)
  410. {
  411. ((A*)this)->buffer = p;
  412. }
  413.  
  414. int NoParamsTest()
  415. {
  416. return ((A*)this)->dummy;
  417. }
  418. int NoParamsTestConst() const
  419. {
  420. return ((A*)this)->dummy;
  421. }
  422.  
  423. string SomeOtherTest(int i, int& j)
  424. {
  425. j = i;
  426. return ((A*)this)->buffer2;
  427. }
  428.  
  429. int TakeThree(int i, int j, int k)
  430. {
  431. return i + j + k;
  432. }
  433.  
  434. int TakeFour(int i, int j, int k, int l)
  435. {
  436. return i + j + k + l;
  437. }
  438.  
  439. int TakeThreeConst(int i, int j, int k) const
  440. {
  441. return i + j + k;
  442. }
  443.  
  444. int TakeFourConst(int i, int j, int k, int l) const
  445. {
  446. return i + j + k + l;
  447. }
  448.  
  449. int TakeFive(int i, int j, int k, int l, int m)
  450. {
  451. return i + j + k + l + m;
  452. }
  453.  
  454. double TakeFive2(int i, int j, int k, int l, int m)
  455. {
  456. return i + j + k + l + m;
  457. }
  458.  
  459. int TakeFiveConst(int i, int j, int k, int l, int m) const
  460. {
  461. return i + j + k + l + m;
  462. }
  463.  
  464. double Test2ThisCall(int i, int& j)
  465. {
  466. return 0.1;
  467. }
  468.  
  469. #if defined(_WIN32)
  470. void __stdcall StdCall(char* p)
  471. {
  472. ((A*)this)->buffer = p;
  473. }
  474. double __cdecl Test2Cdecl(int i, int& j)
  475. {
  476. return 0.2;
  477. }
  478. double __stdcall Test2StdCall(int i, int& j)
  479. {
  480. return 0.3;
  481. }
  482. double __fastcall Test2FastCall(int i, int& j)
  483. {
  484. return 0.4;
  485. }
  486. #endif
  487.  
  488. double TestVarArgsThisCall(int i, ...)
  489. {
  490. return 11.;
  491. }
  492.  
  493. double TestVarArgs0ThisCall(...)
  494. {
  495. return 21.;
  496. }
  497. };
  498.  
  499. #define CHECK_EQUAL(a, b) \
  500.   if ((a) == (b)); else cerr << "CHECK_EQUAL failed at " __FILE__ "(" << __LINE__ << ")\n";
  501.  
  502. int main()
  503. {
  504. CXTest test;
  505.  
  506. A* pA = (A*) &test;
  507.  
  508. CHECK_EQUAL("777", pA->Dummy0(777));
  509.  
  510. int i = 999;
  511. CHECK_EQUAL("-999", pA->Dummy0(&i));
  512.  
  513. pA->Dummy2("YetAnotherTest");
  514. CHECK_EQUAL("YetAnotherTest", pA->buffer);
  515.  
  516.  
  517. pA->dummy = 3456;
  518. CHECK_EQUAL(3456, pA->Dummy3());
  519. CHECK_EQUAL(3456, pA->Dummy3Const());
  520.  
  521. int j = 0;
  522. pA->buffer2 = "This would be to miss an opportunity.";
  523. CHECK_EQUAL("This would be to miss an opportunity.", pA->SomeOtherTest(i, j));
  524. CHECK_EQUAL(i, j);
  525.  
  526. CHECK_EQUAL(6, pA->TakeThree(1, 2, 3));
  527. CHECK_EQUAL(10, pA->TakeFour(1, 2, 3, 4));
  528.  
  529. CHECK_EQUAL(6, pA->TakeThreeConst(1, 2, 3));
  530. CHECK_EQUAL(10, pA->TakeFourConst(1, 2, 3, 4));
  531.  
  532. CHECK_EQUAL(15, pA->TakeFive(1, 2, 3, 4, 5));
  533. CHECK_EQUAL(15, pA->TakeFiveConst(1, 2, 3, 4, 5));
  534.  
  535. CHECK_EQUAL(0.1, pA->Test2ThisCall(1, j));
  536. #if defined(_WIN32)
  537. pA->StdCall("StdCallTest");
  538. CHECK_EQUAL("StdCallTest", pA->buffer);
  539. CHECK_EQUAL(0.2, pA->Test2Cdecl(1, j));
  540. CHECK_EQUAL(0.3, pA->Test2StdCall(1, j));
  541. CHECK_EQUAL(0.4, pA->Test2FastCall(1, j));
  542. #endif
  543.  
  544. CHECK_EQUAL(11., pA->TestVarArgsThisCall(1, j));
  545. CHECK_EQUAL(21., pA->TestVarArgs0ThisCall(1, j));
  546.  
  547. std::cout << "ok.\n";
  548. }
  549.  
Success #stdin #stdout 0s 3484KB
stdin
Standard input is empty
stdout
ok.