// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. /*defines*/ #ifndef TIME_DISCRETE_MICRO_MOCK_H #define TIME_DISCRETE_MICRO_MOCK_H #pragma once #include "stdafx.h" #include "micromock.h" typedef unsigned int UINT32; #define TD_MOCK_CLASS(className) \ class Typed_##className; \ typedef CTimeDiscreteMicroMock className; \ TYPED_MOCK_CLASS(Typed_##className, CThreadSafeGlobalMock) // A strict expected call implies that all arguments are checked #define STRICT_EXPECTED_CALL_AT(ClassName, time, ...) \ STRICT_EXPECTED_CALL(ClassName, __VA_ARGS__) \ .AddExtraCallArgument(new CMockCallArgument(time, false)) // By using the below macro, none of the arguments are checked by default // To specify checking the argument values, use the ValidateArgument // expected call modifier method #define EXPECTED_CALL_AT(ClassName, time, ...) \ STRICT_EXPECTED_CALL_AT(ClassName, time, __VA_ARGS__) \ .IgnoreAllArguments() /*this macro takes a mock name, looks it up in the repository, and gets the time provider for that mock*/ #define MOCK_TIMEPROVIDER(mockName) \ (dynamic_cast(GetSingleton())->getCurrentTick()) /*a poor interface that says "I know how to play"*/ class canPlay { public: virtual void PlayTick(_In_ UINT32 time, _In_ UINT32 order)=0; virtual ~canPlay()=0; }; inline canPlay::~canPlay(){} template class valueHolder { private: T theValue; public: valueHolder(_In_ const T& t) { theValue = t; } void operator=(_In_ T& t) { theValue = t; } operator T*(void) { return &theValue; } operator T&(void) { return theValue; } void setArraySize(_In_ size_t size) { UNREFERENCED_PARAMETER(size); ASSERT_FAIL("Setting an array size for something that is not a pointer is CATASTROPHIC failure"); } }; /*template template parameter partial specialization, or something*/ template class valueHolder { private: bool wasNULL; T theValue; T* originalPointer; T* copyArray; size_t arraySize; private: void SetValue(_In_ T* t) { if(t==NULL) { wasNULL = true; } else { wasNULL = false; theValue = *t; originalPointer = t; arraySize = 0; } } public: valueHolder(_In_ T* t) : copyArray(NULL) { SetValue(t); } valueHolder(_In_ const valueHolder & t): wasNULL(t.wasNULL), theValue(t.theValue), originalPointer(t.originalPointer), arraySize(t.arraySize) { if(t.copyArray!=NULL) { copyArray = new T[t.arraySize]; ASSERT_IS_TRUE(NULL != copyArray, _T("memory error")); for(size_t i=0;i class valueHolder { private: bool wasNULL; T theValue; const T* originalPointer; T* copyArray; size_t arraySize; private: void SetValue(_In_ const T* t) { if(t==NULL) { wasNULL = true; } else { wasNULL = false; theValue = *t; originalPointer = t; arraySize = 0; } } public: valueHolder(_In_ const T* t) : copyArray(NULL) { SetValue(t); } valueHolder(_In_ const valueHolder & t): wasNULL(t.wasNULL), theValue(t.theValue), originalPointer(t.originalPointer), arraySize(t.arraySize) { if(t.copyArray!=NULL) { copyArray = new T[t.arraySize]; ASSERT_IS_TRUE(NULL != copyArray, _T("memory error")); for(size_t i=0;i class valueHolder { private: std::string theValue; public: valueHolder(_In_z_ char* t) { theValue = t; } void operator=(_In_z_ char* t) { theValue = t; } operator char*(void) { return (char*)(theValue.c_str()); } }; /*this is a special case*/ template <> class valueHolder { private: std::wstring theValue; public: valueHolder(_In_z_ wchar_t* t) { theValue = t; } void operator=(_In_z_ wchar_t* t) { theValue = t; } operator wchar_t*(void) { return (wchar_t*)theValue.c_str(); } }; class stims_base { /*friends because registerCallXArg should not be available as public*/ template friend class call0Arg; template friend class call1Arg; template friend class call2Arg; template friend class call3Arg; template friend class call4Arg; template friend class call5Arg; template friend class call6Arg; template friend class call7Arg; template friend class call8Arg; template friend class call9Arg; template friend class call10Arg; template friend class call11Arg; template friend class call12Arg; template friend class call13Arg; template friend class call14Arg; template friend class call15Arg; private: static std::vector allPlayers; static void registerCallXArg(canPlay* someStim) { allPlayers.push_back(someStim); } public: virtual ~stims_base() { allPlayers.clear(); } void static PlayTick(_In_ UINT32 tick, _In_ UINT32 order) { for(UINT32 i=0;iPlayTick(tick, order); } } }; #include "timediscretemicromockcallmacros.h" extern UINT32 theTick; extern UINT32 totalTicksPlayed; #define MAXTICK 1000000 class CTimeDiscreteMicroMockBase : public stims_base { private: UINT32 m_currentTick; void(*m_theTask)(void); UINT32*maxOrder; public: /*the only constructor will accept a task given as function name*/ CTimeDiscreteMicroMockBase(_In_opt_ void(*p)(void)) :m_theTask(p) { maxOrder = (UINT32*)malloc(MAXTICK*sizeof(UINT32)); if (maxOrder == NULL) { MOCK_THROW(_T("out of memory")); } else { memset(maxOrder, 0xFF, MAXTICK*sizeof(UINT32)); } } virtual ~CTimeDiscreteMicroMockBase() { if (maxOrder != NULL) { free(maxOrder); maxOrder = NULL; } } void RunUntilTick(_In_ UINT32 nTick) { totalTicksPlayed += nTick; if (nTick >= MAXTICK) { MOCK_THROW(_T("time detected bigger than MAXTICK")); } for (UINT32 i = 0; i <= nTick; i++) { m_currentTick = i; theTick = m_currentTick; if (maxOrder[i] != 0xFFFFFFFF) { for (UINT32 order = 0; order <= maxOrder[i]; order++) { stims_base::PlayTick(i, order); } } m_theTask(); } } UINT32 getCurrentTick(void) { return m_currentTick; } UINT32 getAndIncOrder(_In_ UINT32 time) { if (time class CTimeDiscreteMicroMock: public T, public CTimeDiscreteMicroMockBase { public: CTimeDiscreteMicroMock(void (*theTask)(void)):CTimeDiscreteMicroMockBase(theTask) { } }; /*variable exports*/ /*function exports*/ #endif