BoundFunction.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2006-2007 by Peter Dimov.
00004 
00005 This file is part of Calitko (http://www.calitko.org).
00006 
00007 Calitko is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 Calitko is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Calitko; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 */
00022 
00023 #ifndef UTILS__CALITKO_MOCKS__BOUND_FUNCTION_H
00024 #define UTILS__CALITKO_MOCKS__BOUND_FUNCTION_H
00025 
00026 #include "Imports.h"
00027 #include "BasicTypes.h"
00028 
00029 // Define some macros to help us define the template specializations:
00030 #include "HelperMacros.h"
00031 
00032 namespace Utils {
00033 namespace CalitkoMocks {
00034 
00035 class ExpectedFunctionBase;
00036 
00038 class BoundFunctionBase
00039 {
00040 public:
00041                     BoundFunctionBase();
00042     virtual         ~BoundFunctionBase();
00043 
00044     void            addExpectation (ExpectedFunctionBase *);
00045     void            setContext (const std::string &expectationString_,
00046                                 const SourceLine &sourceLine_);
00047     virtual void    call() = 0;
00048     void            checkCalled();
00049 
00050 protected:
00051     void            fail (const std::string &reason);
00052     void            checkExpectations();
00053 
00054     bool            wasCalled;
00055 
00056 protected:
00057     std::string     expectationString;
00058     SourceLine      sourceLine;
00059 
00060 private:
00061     Q_DISABLE_COPY (BoundFunctionBase)
00062 
00063     typedef std::list <ExpectedFunctionBase *>  Expectations;
00064     Expectations                                expectations;
00065 };
00066 
00068 
00098 template <typename Host, typename Func = void()>
00099 class BoundFunction;
00100 
00102 #define DEFINE_BOUND_FUNCTION(N)                                            \
00103     template <typename Host,                                                \
00104               typename R COMMA_ARGUMENTS_TYPE_LIST_##N (typename P)>        \
00105     class BoundFunction <Host, R (ARGUMENTS_TYPE_LIST_##N(P))>              \
00106         : public BoundFunctionBase                                          \
00107     {                                                                       \
00108         REFERENCE_OBJECT (BoundFunction)                                    \
00109     public:                                                                 \
00110         typedef BoundFunctionBase   Base;                                   \
00111         typedef R   (Host::*FunctionPointer) (ARGUMENTS_TYPE_LIST_##N(P));  \
00112         typedef R   (Host::*ConstFunctionPointer)                           \
00113                                     (ARGUMENTS_TYPE_LIST_##N(P)) const;     \
00114         typedef R   ReturnType;                                             \
00115                                                                             \
00116         BoundFunction (Host *h, FunctionPointer f COMMA_PARAMETER_LIST_##N) \
00117         : host (h), function (f), stubbedReturnValue()                      \
00118           INITIALIZER_LIST_##N {}                                           \
00119                                                                             \
00120         /* This ctor is a quick HACK to bind const member functions too */  \
00121         BoundFunction (const Host *h, ConstFunctionPointer f                \
00122                                                 COMMA_PARAMETER_LIST_##N)   \
00123         : host (const_cast <Host*> (h)),                                    \
00124           function (reinterpret_cast <FunctionPointer> (f)),                \
00125           stubbedReturnValue()                                              \
00126           INITIALIZER_LIST_##N {}                                           \
00127                                                                             \
00128         void willReturn (ReturnTypeWrapper <ReturnType> r)                  \
00129         { stubbedReturnValue.reset (new ReturnTypeWrapper <ReturnType>(r));}\
00130                                                                             \
00131         void call()                                                         \
00132         { this->wasCalled = true;                                           \
00133           if (!IsSameType <ReturnType, void>::value                         \
00134               && (stubbedReturnValue.get() == 0))                           \
00135             this->fail ("willReturn() not called for");                     \
00136           try {                                                             \
00137             if (!doCall (*stubbedReturnValue.get()))                        \
00138                 this->fail ("willReturn() expectation failed");             \
00139           } catch (Exception &e) {                                          \
00140             /* If no context is given, set ours, but keep the message.*/    \
00141             if (e.sourceLine() == SourceLine())                             \
00142                 throw Exception (e.message(), this->sourceLine);            \
00143             else                                                            \
00144                 throw;                                                      \
00145           }                                                                 \
00146         }                                                                   \
00147                                                                             \
00148     private:                                                                \
00149         R operator() ()                                                     \
00150         { return (host->*function) (ARGUMENTS_TYPE_LIST_##N(a)); }          \
00151                                                                             \
00152         template <typename T> bool doCall(const ReturnTypeWrapper <T> &r)   \
00153         { bool ok = (r.value == (*this)());                                 \
00154           this->checkExpectations(); return ok; }                           \
00155                                                                             \
00156         bool doCall (const ReturnTypeWrapper <void> &)                      \
00157         { (*this)(); this->checkExpectations(); return true; }              \
00158                                                                             \
00159         Host                                *host;                          \
00160         FunctionPointer                     function;                       \
00161         auto_ptr <ReturnTypeWrapper <ReturnType> >                          \
00162                                             stubbedReturnValue;             \
00163         DECLARE_BOUND_VARIABLES_##N                                         \
00164     };
00165 
00166 DEFINE_BOUND_FUNCTION(0)
00167 DEFINE_BOUND_FUNCTION(1)
00168 DEFINE_BOUND_FUNCTION(2)
00169 DEFINE_BOUND_FUNCTION(3)
00170 DEFINE_BOUND_FUNCTION(4)
00171 DEFINE_BOUND_FUNCTION(5)
00172 DEFINE_BOUND_FUNCTION(6)
00173 DEFINE_BOUND_FUNCTION(7)
00174 DEFINE_BOUND_FUNCTION(8)
00175 DEFINE_BOUND_FUNCTION(9)
00176 
00177 #undef DEFINE_BOUND_FUNCTION
00178 
00179 } // namespace CalitkoMocks
00180 } // namespace Utils
00181 
00182 // Undefine the helper macros. Yes, including the file again undefs them all!
00183 #include "HelperMacros.h"
00184 
00185 #endif // UTILS__CALITKO_MOCKS__BOUND_FUNCTION_H