Click here to Skip to main content
15,897,518 members
Articles / Desktop Programming / ATL

Test Runner Application

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
2 Nov 2005 106.3K   1.7K   27  
A framework for performing unit tests.
#if !defined(CPROPERTYTESTER_H_A2EFEBC1_921D_11d3_AC01_00508B0D0D6E)
#define CPROPERTYTESTER_H_A2EFEBC1_921D_11d3_AC01_00508B0D0D6E

#if _MSC_VER > 100
#pragma once
#endif // _MSC_VER > 100

// 
//                Jerry Edens & Doug Eveland
//         Copyright(c) 1999 All Rights Reserved 
// 
// This code may be used in compiled form for non-profit
// purposes and the source code may be redistributed 
// unmodified by any means providing it is not sold for 
// profit, unless written consent is granted by the 
// authors, and providing that this notice and the 
// authors names are included.
//
// If you find any bugs or make any modifications please
// send them to me for incorporation into the code.
//
// This file is provided "as is" with out expressed or 
// implied warranty.
//
// Contact me if you have any questions, comments, or 
// bug reports at jerrye@home.com
//
// Description:
// 	 Tests a set of properties associated with the interface.
// 
// $Log: 
// $
// $Revision: $
// $Date: $
// Author: Jerry Edens
// 
// CPropertyTester.h : Definition of CPropertyTester

#if !defined(__ATLBASE_H__)
#error "The AtlBase.h file must be included first."
#endif
#if !defined(CHECK_HR)
#error "CHECK_HR must be defined!"
#endif
#if !defined(RESERVED)
//#error "RESERVED must be defined, normally as 0"
#define RESERVED 0
#endif

#include <map>

// Group = Helper Classes

// 
// Description:
// 	Test the properties of the object.
//
// Author:
// 	Jerry Edens
//
// Include: 
//    #include "CPropertyTester.h"
//
class CPropertyTester
{ 
   // {secret} 
   struct InvokeInfo
   {
      CComPtr<IDispatch> pDispatch; 
      UINT uInvKind;
      CComPtr<ITypeInfo> pITypeInfo; 
      FUNCDESC funcDesc;
      CComPtr<ITestOutput> pTestOutput;
   };

   // These maps hold the put and get information about the properties
   // They are held in seperate maps for the following reasons:
   // 1. The order of the get and puts can not be know before hand.
   //    To propertly test the get and puts the put must be done first
   //    then a get.
   // 2. The properties have the same name so keep them in seperate maps.
   // {secret} 
   typedef std::map< CAdapt< CComBSTR >, InvokeInfo> GetPropertyInfoMap;
   // {secret} 
   typedef std::map< CAdapt< CComBSTR >, InvokeInfo> PutPropertyInfoMap;

public: 

	// Group = Constructors
   
   CPropertyTester()
   {
      bVerbose = false;
   }

   virtual ~CPropertyTester()
   {
      m_getPropertyInfoMap.clear();
      m_putPropertyInfoMap.clear();
   }
	
	// Group = Operations

   // 
   // Name: 
   // 	TestProperties
   // 
   // Description:
   // 	Tests the properties of the interface using IDispatch::Invoke.
   // 
   // Arguments:
   // 	ISupportOutput* pOutput - Used to ouput result messages.
   // 
   // 	IDispatch* - The interface whose properties are to be tested.
   // 
   // Returns:
   //    S_OK - All is well
   //    E_INVALIDARG - The argument is NULL or out of range.
   //    E_UNEXPECTED - An unexpected error has occured.
   //
   virtual HRESULT TestProperties(ITestOutput* pTestOutput, 
         IDispatch* pDispatch)
   {
      ATLASSERT(pTestOutput != NULL);
      ATLASSERT(!::IsBadReadPtr(pTestOutput, sizeof(pTestOutput)));
      ATLASSERT(pDispatch != NULL);
      ATLASSERT(!::IsBadReadPtr(pDispatch, sizeof(pDispatch)));

      HRESULT hr = S_OK;

      try
      {
         processMessage(pTestOutput, _bstr_t(L"Entering CPropertyTester::TestProperties()"));

         if (pTestOutput == NULL || pDispatch == NULL)
         {
            hr = E_INVALIDARG;
            processMessage(pTestOutput, _bstr_t(L"Invalid argument. Either pTestOutput or pDispatch is null!"));
            throw hr;
         }

         // find all the properties in the component

         // determine if the object exposes type information
         UINT cntTypeInfo;
         hr = pDispatch->GetTypeInfoCount(&cntTypeInfo);
         CHECK_HR(hr);

         // The the type information  ITypeInfo
         CComPtr<ITypeInfo> pITypeInfo;
         hr = pDispatch->GetTypeInfo(RESERVED, 0, &pITypeInfo);
         CHECK_HR(hr);

         //ATLTRACE("Retrieving the type info succeeded\n");
         
         TYPEATTR* pTypeAttr = NULL;
         hr = pITypeInfo->GetTypeAttr(&pTypeAttr);
         CHECK_HR(hr);

         // copy the contents locally 
         TYPEATTR typeAttr = *pTypeAttr;
         // release the TYPEATTR resource
         pITypeInfo->ReleaseTypeAttr(pTypeAttr);

         // loop through and look at each interface
         UINT cntFuncNames = typeAttr.cFuncs;
         for (UINT i = 0; i < cntFuncNames; i++)
         {
            FUNCDESC* pFuncDesc = NULL;
            hr = pITypeInfo->GetFuncDesc(i, &pFuncDesc);
            CHECK_HR(hr);

            // Only test properties
            if (pFuncDesc->invkind == INVOKE_PROPERTYGET ||
               pFuncDesc->invkind == INVOKE_PROPERTYPUT ||
               pFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
            {
		        
               CComBSTR bstrPropertyName;
               pITypeInfo->GetDocumentation(pFuncDesc->memid, &bstrPropertyName, null, null, null);

#if defined (_DEBUG) && defined (_SHOW_PROPERY_NAME)
               CComBSTR bstrExplanation(bstrPropertyName);
               bstrExplanation.Append(L" is a ");
               bstrExplanation.Append((pFuncDesc->invkind == INVOKE_PROPERTYGET ? L"get" : L"put"));
               bstrExplanation.Append(L" property... ");
               processMessage(pTestOutput, _bstr_t(bstrExplanation));
#endif

               UINT uInvKind = (pFuncDesc->invkind == INVOKE_PROPERTYGET ? DISPATCH_PROPERTYGET :
                     (pFuncDesc->invkind == INVOKE_PROPERTYPUT ? 
                        DISPATCH_PROPERTYPUT : DISPATCH_PROPERTYPUTREF));

               InvokeInfo invokeInfo;
               invokeInfo.funcDesc = *pFuncDesc;
               invokeInfo.pDispatch = pDispatch; 
               invokeInfo.pITypeInfo = pITypeInfo;
               invokeInfo.pTestOutput = pTestOutput; 
               invokeInfo.uInvKind = uInvKind;

               if (uInvKind == DISPATCH_PROPERTYGET)
               {
                  m_getPropertyInfoMap[bstrPropertyName] = invokeInfo;
               }
               else
               {
                  m_putPropertyInfoMap[bstrPropertyName] = invokeInfo;
               }
                
            }                       
         
            pITypeInfo->ReleaseFuncDesc(pFuncDesc);
           // find the min max values for each property
         }

         PutPropertyInfoMap::iterator putIterBegin;
         PutPropertyInfoMap::iterator putIterEnd;
         putIterBegin = m_putPropertyInfoMap.begin();
         putIterEnd = m_putPropertyInfoMap.end();
         while (putIterBegin != putIterEnd)
         {
            InvokeInfo invokeInfo = (*putIterBegin).second;
            hr = handleInvoke(invokeInfo.pDispatch, invokeInfo.uInvKind, 
                  invokeInfo.pITypeInfo, &invokeInfo.funcDesc, invokeInfo.pTestOutput);
            if (FAILED(hr))
            {
               _bstr_t bstrMessage(L"Invoking ");
               bstrMessage += (invokeInfo.funcDesc.invkind == INVOKE_PROPERTYGET ? L"get_" : L"put_");
               //bstrMessage += bstrPropertyName.m_str;
               bstrMessage += static_cast<BSTR>((*putIterBegin).first.m_T);
               bstrMessage += L" failed.";
               processError(invokeInfo.pTestOutput, hr, bstrMessage);
            }

            putIterBegin++;
         }  // while (iterBegin != iterEnd)

         GetPropertyInfoMap::iterator getIterBegin;
         GetPropertyInfoMap::iterator getIterEnd;
         getIterBegin = m_getPropertyInfoMap.begin();
         getIterEnd = m_getPropertyInfoMap.end();
         while (getIterBegin != getIterEnd)
         {
            InvokeInfo invokeInfo = (*getIterBegin).second;
            hr = handleInvoke(invokeInfo.pDispatch, invokeInfo.uInvKind, 
                  invokeInfo.pITypeInfo, &invokeInfo.funcDesc, invokeInfo.pTestOutput);
            if (FAILED(hr))
            {
               _bstr_t bstrMessage(L"Invoking ");
               bstrMessage += (invokeInfo.funcDesc.invkind == INVOKE_PROPERTYGET ? L"get_" : L"put_");
               //bstrMessage += bstrPropertyName.m_str;
               bstrMessage += static_cast<BSTR>((*getIterBegin).first.m_T);
               bstrMessage += L" failed.";
               processError(invokeInfo.pTestOutput, hr, bstrMessage);
            }

            getIterBegin++;
         }  // while (getIterBegin != getIterEnd)
      }
      catch(HRESULT hr)
      {
         processError(pTestOutput, hr, _bstr_t(L"Caught thrown HRESULT. "));
      }
      catch(_com_error& re)
      {
         hr = re.Error();
         processError(pTestOutput, hr, _bstr_t(L"Caught thrown _com_error. "));
      }
      catch(...)
      {
         hr = E_UNEXPECTED;
         processError(pTestOutput, hr, _bstr_t(L"Caught thrown exception. "));
      }
      
      processMessage(pTestOutput, _bstr_t(L"Exiting CPropertyTester::TestProperties()"));

      return(hr);
   }

   // Group=Virtual Data Members

   // 
   // Name:
   //    bVerbose
   // 
   // Description:
   //    bVerbose is used to determine how much information to 
   //    put out to the log file.  When it is true, more information 
   //    is placed out onto the file.
   // 
   // Remarks:
   //    The default value is false.
   //
   __declspec( property( get=GetbVerbose, put=PutbVerbose ) ) VARIANT_BOOL bVerbose;

   // {secret} 
   VARIANT_BOOL GetbVerbose(){VARIANT_BOOL b; get_bVerbose(&b); return b;}
   // {secret} 
   void PutbVerbose(VARIANT_BOOL newB){put_bVerbose(newB);}

   // {secret} 
   // 
   // Name: 
   // 	get_bVerbose
   // 
   // Description:
   // 	Implementation for the bVerbose property.
   // 
   // Arguments:
   // 	pBool - Holder for the result.
   // 
   void get_bVerbose(VARIANT_BOOL* pBool){ATLASSERT(pBool != NULL); *pBool = m_bVerbose;}

   // {secret} 
   // 
   // Name: 
   //    put_bVerbose 
   // 
   // Description:
   // 	Implementation for the bVerbose property.
   // 
   // Arguments:
   //    newBool - The new value to set.
   // 
   void put_bVerbose(VARIANT_BOOL newBool){m_bVerbose = newBool;}
	

	protected: 
	
   // {secret} 
   // 
   // Name: 
   // 	processMessage
   // 
   // Description:
   // 	Puts the text out to the log. Dependent on the verbose flag.
   // 
   // Arguments:
   // 	pTestOutput - The pointer to the log.
   // 
   // 	bstrMessage - The message to be logged.
   // 
   virtual void processMessage(ITestOutput* pTestOutput, _bstr_t bstrMessage)
   {
      ATLASSERT(pTestOutput != NULL);
      ATLASSERT(!::IsBadReadPtr(pTestOutput, sizeof(ITestOutput*)));

      if (bVerbose && pTestOutput)
      {
         pTestOutput->LogResult(bstrMessage, VARIANT_FALSE);
      }
   }

   // {secret} 
   // 
   // Name: 
   // 	processError
   // 
   // Description:
   // 	Puts the error message onto the log file dependent on the HRESULT passed in.
   // 
   // Arguments:
   // 	pTestOutput - The log onto which to put the message.
   // 
   // 	hr - The error value to base the message on.
   // 
   // 	bstrPrefixInfo - Additional text which gets prefixed onto the message.
   // 
   virtual void processError(ITestOutput* pTestOutput, HRESULT hr, _bstr_t bstrPrefixInfo)
   {
      ATLASSERT(pTestOutput != NULL);
      ATLASSERT(!::IsBadReadPtr(pTestOutput, sizeof(ITestOutput*)));

      LPTSTR sztMessage = NULL;

      try
      {
         if (pTestOutput)
         {
            DWORD dwFlags = 
               FORMAT_MESSAGE_IGNORE_INSERTS | 
               FORMAT_MESSAGE_ALLOCATE_BUFFER |
               FORMAT_MESSAGE_FROM_SYSTEM; 

            // Tells the os to allocate the string buffer
            // so it must be freed.
            FormatMessage(
                  dwFlags, 
                  0,
                  hr, 
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), 
                  reinterpret_cast<LPTSTR>(&sztMessage), 
                  0, 
                  NULL); 
   
            // clean off any cr-lf's
            if ((sztMessage != NULL && sztMessage[0] != '\0') && 
                  sztMessage[_tcslen(sztMessage) - 1] == '\n')
            {
               sztMessage[_tcslen(sztMessage) - 1] = '\0';
            }
      
            // Prepend the text with any extra info supplied.
            _bstr_t bstrMessage;
            if (bstrPrefixInfo.length() > 0)
            {
               bstrMessage += bstrPrefixInfo;
               bstrMessage += L"  ";
            }

            // Now add the error info to the message.
            bstrMessage += L"Exception: hr = ";
            TCHAR szHR[100];
            wsprintf(szHR, _T("0x%8x, "), hr);
            bstrMessage += szHR;
            bstrMessage += sztMessage;
         
            processMessage(pTestOutput, bstrMessage);
         
            ATLTRACE(static_cast<char*>(bstrMessage));
         }
      }
      catch(...)
      {
      }
      
      LocalFree(sztMessage);
   }

private: 
	
   // {secret}
   #define CASE_STRING( x ) \
      case x: \
         s = _T(#x); \
         break; 

   // {secret}
   // 
   // Name: 
   // 	GetTypeKindName
   // 
   // Description:
   // 	Retrieves the type kind name as a string.
   // 
   // Arguments:
   // 	typekind - The type kind
   // 
   // Results:
   // 	The type kind in the form of a string
   // 
   LPCTSTR GetTypeKindName( TYPEKIND typekind )
   {
      LPTSTR s = _T("<unknown>");
      switch ( typekind )
      {
         CASE_STRING ( TKIND_ENUM )
         CASE_STRING ( TKIND_RECORD )
         CASE_STRING ( TKIND_MODULE )
         CASE_STRING ( TKIND_INTERFACE )
         CASE_STRING ( TKIND_DISPATCH )
         CASE_STRING ( TKIND_COCLASS )
         CASE_STRING ( TKIND_ALIAS )
         CASE_STRING ( TKIND_UNION )
      }
      return s;
   }

   // {secret}
   // 
   // Name: 
   // 	GetInvokeKindName
   // 
   // Description:
   // 	Returns the type of function or property.
   // 
   // Arguments:
   // 	invkind - The invoke kind of the function
   // 
   // Results:
   // 	The invoke kind in the form of a string.
   // 
   LPCTSTR GetInvokeKindName( INVOKEKIND invkind )
   {
      LPTSTR s = _T("<unknown>");
      switch ( invkind )
      {       
         CASE_STRING ( INVOKE_FUNC )
         CASE_STRING ( INVOKE_PROPERTYGET )
         CASE_STRING ( INVOKE_PROPERTYPUT )
         CASE_STRING ( INVOKE_PROPERTYPUTREF )
      }    
      return s;
   }

   // {secret}
   // 
   // Name: 
   // 	GetCallingConventionAsText
   // 
   // Description:
   // 	Retrieves the Calling convention as text
   // 
   // Arguments:
   // 	callConv - The calling convention type
   // 
   // Results:
   // 	The calling type as a string
   // 
   LPCTSTR GetCallingConventionAsText(CALLCONV callConv)
   {
      LPTSTR s = _T("<unknown>");
      switch ( callConv )
      {
         case CC_FASTCALL:
            s = _T("__fastcall");
            break;
         case CC_CDECL:
            s = _T("__cdecl");
            break;
         //case CC_MSCPASCAL:
         case CC_PASCAL:
            s = _T("__pascal");
            break;
         case CC_MACPASCAL:
            s = _T("__macpascal");
            break;
         case CC_STDCALL:
            s = _T("__stdcall");
            break;
         case CC_FPFASTCALL:
            s = _T("__fpfastcall");
            break;
         case CC_SYSCALL:
            s = _T("__syscall");
            break;
         case CC_MPWCDECL:
            s = _T("__mpwcdecl");
            break;
         case CC_MPWPASCAL:
            s = _T("_mpwpascal");
            break;
      }
      return s;
   }

   // {secret}
   // 
   // Name: 
   // 	GetFunctionTypeAsStirng
   // 
   // Description:
   // 	Returns the funtion type as a string.
   // 
   // Arguments:
   // 	funcKind - The function kind
   // 
   // Results:
   // 	The function type as a string
   // 
   LPCTSTR GetFunctionTypeAsStirng(FUNCKIND funcKind)
   {
      LPTSTR s = _T("<unknown>");
      switch ( funcKind )
      {
         case FUNC_VIRTUAL:
            s = _T("virtual");
            break;
         case FUNC_PUREVIRTUAL:
            s = _T("pure virtual");
            break;
         case FUNC_NONVIRTUAL:
            s = _T("non virtual");
            break;
         case FUNC_STATIC:
            s = _T("static");
            break;
         case FUNC_DISPATCH:
            s = _T("dispatch");
            break;
      }
      return s;
   }

   
   // {secret}
   // 
   // Name: 
   // 	handleInvoke
   // 
   // Description:
   // 	Performs needs steps to call invoke on the property
   // 
   // Arguments:
   // 	pDispatch - The IDispatch pointer which is to be tested.
   // 
   // 	uInvKind - The type of property
   // 
   // 	ITypeInfo* pITypeInfo - Points to the typeInfo for this function.  
   //    Currently not used.
   // 
   // 	pFuncDesc - The function description 
   // 
   // 	pTestOutput - Points to the output hook
   // 
   HRESULT handleInvoke(IDispatch* pDispatch, UINT uInvKind, 
         ITypeInfo* pITypeInfo, FUNCDESC* pFuncDesc, 
         ITestOutput* pTestOutput)
   {
      ATLASSERT(pDispatch != NULL);
      ATLASSERT(!::IsBadReadPtr(pDispatch, sizeof(IDispatch*)));
      ATLASSERT(pITypeInfo != NULL);
      ATLASSERT(!::IsBadReadPtr(pITypeInfo, sizeof(ITypeInfo*)));
      ATLASSERT(pFuncDesc != NULL);
      ATLASSERT(!::IsBadReadPtr(pFuncDesc, sizeof(FUNCDESC*)));
      ATLASSERT(pTestOutput != NULL);
      ATLASSERT(!::IsBadReadPtr(pTestOutput, sizeof(ITestOutput)));

      EXCEPINFO excepInfo = {0};
      WORD wFlags = 0;
      UINT uArgErr = 0;
      DISPID dispId[1] = {0};
      CComVariant vars[1];
      CComVariant varResult;
      DISPPARAMS dispParams[1] = {0};
      
      HRESULT hr = E_FAIL; 

      try
      {
         if (pDispatch == NULL || pITypeInfo == NULL || pFuncDesc == NULL || pTestOutput == NULL)
         {
            hr = E_INVALIDARG;
            CHECK_HR(hr);
         }

         switch (uInvKind)
         {
            case INVOKE_PROPERTYGET: 
            {
               wFlags = DISPATCH_PROPERTYGET;
            
               dispParams[0].rgvarg = NULL;
               dispParams[0].cArgs = 0;
               dispParams[0].rgdispidNamedArgs = NULL;
               dispParams[0].cNamedArgs = 0;
               break;
            }
            case INVOKE_PROPERTYPUT:
            {
               wFlags = DISPATCH_PROPERTYPUT;
               dispId[0] = DISPID_PROPERTYPUT;
            
               fillVariant(vars[0], pFuncDesc, pITypeInfo, pTestOutput);
	   	      
               dispParams[0].rgvarg = vars;
               dispParams[0].cArgs = 1;
               dispParams[0].rgdispidNamedArgs = dispId;
               dispParams[0].cNamedArgs = 1;
               break;
            }
            case INVOKE_PROPERTYPUTREF:
            {
               wFlags = DISPATCH_PROPERTYPUTREF;
               dispId[0] = DISPID_PROPERTYPUT;
            
               fillVariant(vars[0], pFuncDesc, pITypeInfo, pTestOutput);
            
               dispParams[0].rgvarg = vars;
               dispParams[0].cArgs = 1;
               dispParams[0].rgdispidNamedArgs = dispId;
               dispParams[0].cNamedArgs = 1;
               break;
            }
            default:
               ATLASSERT(FALSE);
         }

         hr = pDispatch->Invoke(pFuncDesc->memid, IID_NULL, LOCALE_USER_DEFAULT,
               wFlags, dispParams, &varResult, &excepInfo, &uArgErr);

         CComBSTR bstrPropertyName;
         pITypeInfo->GetDocumentation(pFuncDesc->memid, &bstrPropertyName, null, null, null);

         _bstr_t bstrMessage = L"The test of ";
         bstrMessage += (wFlags == DISPATCH_PROPERTYGET ? L"get_" : L"put_");
         bstrMessage += bstrPropertyName.m_str;
      
         // Did the invoke succeeded ?
         if (SUCCEEDED(hr))
         {
            bstrMessage += L", succeeded";
         }
         else
         {
            wchar_t szErrorCode[50];
            swprintf(szErrorCode, L"0x%08x", hr);
            bstrMessage += L", failed with hr = ";
            bstrMessage += szErrorCode;
         }

         pTestOutput->LogResult(bstrMessage, VARIANT_FALSE);

         if (uInvKind == INVOKE_PROPERTYGET)
         {
            logVar(varResult, pTestOutput);
         }
         else
         {
            logVar(vars[0], pTestOutput);
         }
      }
      catch(...)
      {
         hr = E_UNEXPECTED;
      }
            
      return(hr);
   }

   // {secret}
   // 
   // Name: 
   // 	fillVariant
   // 
   // Description:
   // 	Fills the variant with some sample data
   // 
   // Arguments:
   // 	var - The variant which is to be set.
   // 
   // 	pFuncDesc - The function description
   // 
   // 	pITypeInfo - The type information
   // 
   // 	pTestOutput - The log output hook
   // 
   // Remarks:
   //    This method will fill the data with some more reasonable
   //    data once the persistence layer has been implemented.
   // 
   void fillVariant(CComVariant& var, FUNCDESC* pFuncDesc, ITypeInfo* pITypeInfo, 
         ITestOutput* pTestOutput)
   {
      // 
      // Fix Me!
      // 	This needs to be re-done after the persistence layer is complete.
      // 
      // Jerry Edens, 11/1/99 4:13:17 PM
      // 
      var = 123;
   }

   // {secret}
   // 
   // Name: 
   // 	logVar
   // 
   // Description:
   // 	Logs the variant to the test output.
   // 
   // Arguments:
   // 	rVarResult - The variant to log.
   // 
   // 	pTestOutput - The output hook to log to.
   // 
   void logVar(CComVariant& rVarResult, ITestOutput* pTestOutput)
   {
      // 
      // Fix Me!
      // 	This is an arbitrary value.  
      // 
      // Jerry Edens, 11/1/99 4:13:17 PM
      // 
      USES_CONVERSION;
      TCHAR szMessage[1024] = {0};
            
      switch (rVarResult.vt)
      {
         case VT_UI1:                              //    Byte                bVal;               
         {
            _stprintf(szMessage, _T("The varResult is a Byte, = %c"), rVarResult.bVal);
            break; 
         }

         case VT_I2:                               //    Short               iVal;               
         {
            _stprintf(szMessage, _T("The varResult is a Short, = %d"), rVarResult.iVal);
            break; 
         }

         case VT_I4:                               //    long                lVal;               
         {
            _stprintf(szMessage, _T("The varResult is a long, = %d"), rVarResult.lVal);
            break; 
         }

         case VT_R4:                               //    float               fltVal;             
         {
            _stprintf(szMessage, _T("The varResult is a float, = %g"), rVarResult.fltVal);
            break; 
         }

         case VT_R8:                               //    double              dblVal;             
         {
            _stprintf(szMessage, _T("The varResult is a double, = %g"), rVarResult.dblVal);
            break; 
         }

         case VT_BOOL:                             //    VARIANT_BOOL        boolVal;            
         {
            _stprintf(szMessage, _T("The varResult is a VARIANT_BOOL, = %c"), rVarResult.boolVal);
            break; 
         }

         case VT_ERROR:                            //    SCODE               scode;              
         {
            _stprintf(szMessage, _T("The varResult is a SCODE, = 0x%08x"), rVarResult.scode);
            break; 
         }

         case VT_CY:                               //    CY                  cyVal;              
         {
            _stprintf(szMessage, _T("The varResult is a CURRENCY, = %d"), rVarResult.cyVal.int64);
            break; 
         }

         case VT_DATE:                             //    DATE                date;               
         {
            _stprintf(szMessage, _T("The varResult is a DATE, = %d"), rVarResult.date);
            break; 
         }

         case VT_BSTR:                             //    BSTR                bstrVal;            
         {
            _stprintf(szMessage, _T("The varResult is a BSTR, = %s"), W2T(rVarResult.bstrVal));
            break; 
         }

         case VT_BYREF|VT_DECIMAL:                 //    DECIMAL             FAR* pdeal        
         {
            _stprintf(szMessage, _T("The varResult is a DECIMAL, = %d"), (*rVarResult.pdecVal).Hi32);
            break; 
         }

         case VT_UNKNOWN:                          //    IUnknown            FAR* punkVal;       
         {
            _stprintf(szMessage, _T("The varResult is a IUnknown pointer, = %p"), rVarResult.punkVal);
            break; 
         }

         case VT_DISPATCH:                         //    IDispatch           FAR* pdispVal;      
         {
            _stprintf(szMessage, _T("The varResult is a IDispatch pointer, = %p"), rVarResult.pdispVal);
            break; 
         }

         case VT_ARRAY:                             //    SAFEARRAY           FAR* parray;        
         {
            _stprintf(szMessage, _T("The varResult is a SAFEARRAY"));
            break; 
         }

         case VT_BYREF|VT_UI1:                     //    Byte                FAR* pbVal;         
         {
            _stprintf(szMessage, _T("The varResult is a byte by reference, = %c"), *(rVarResult.pbVal));
            break; 
         }

         case VT_BYREF|VT_I2:                      //    short               FAR* piVal;         
         {
            _stprintf(szMessage, _T("The varResult is a short by reference, = %d"), *(rVarResult.piVal));
            break; 
         }

         case VT_BYREF|VT_I4:                      //    long                FAR* plVal;         
         {
            _stprintf(szMessage, _T("The varResult is a long by reference, = %d"), *(rVarResult.plVal));
            break; 
         }

         case VT_BYREF|VT_R4:                      //    float               FAR* pfltVal;       
         {
            _stprintf(szMessage, _T("The varResult is a float by reference, = %g"), *(rVarResult.pfltVal));
            break; 
         }

         case VT_BYREF|VT_R8:                      //    double              FAR* pdblVal;       
         {
            _stprintf(szMessage, _T("The varResult is a double by reference, = %g"), *(rVarResult.pdblVal));
            break; 
         }

         case VT_BYREF|VT_BOOL:                    //    VARIANT_BOOL        FAR* pboolVal;      
         {
            _stprintf(szMessage, _T("The varResult is a VARIANT_BOOL by reference, = %c"), *(rVarResult.pboolVal));
            break; 
         }

         case VT_BYREF|VT_ERROR:                   //    SCODE               FAR* pscode;        
         {
            _stprintf(szMessage, _T("The varResult is a SCODE by reference, = 0x%08x"), *(rVarResult.pscode));
            break; 
         }

         case VT_BYREF|VT_CY:                      //    CY                  FAR* pcyVal;        
         {
            _stprintf(szMessage, _T("The varResult is a CURRENCY by reference, = %d"), (*(rVarResult.pcyVal)).int64);
            break; 
         }

         case VT_BYREF|VT_DATE:                    //    DATE                FAR* pdate;         
         {
            //_stprintf(szMessage, _T("The varResult is a DATE by reference = %d"), (*(rVarResult.pdate)));
            break; 
         }

         case VT_BYREF|VT_BSTR:                    //    BSTR                FAR* pbstrVal;      
         {
            _stprintf(szMessage, _T("The varResult is a BSTR by reference, = %s"), W2T(*(rVarResult.pbstrVal)));
            break; 
         }

         case VT_BYREF|VT_UNKNOWN:                 //    IUnknown            FAR* FAR* ppunkVal; 
         {
            _stprintf(szMessage, _T("The varResult is a IUnknown* by reference, = %p"), (*(rVarResult.ppunkVal)));
            break; 
         }

         case VT_BYREF|VT_DISPATCH:                //    IDispatch           FAR* FAR* ppdispVal;
         {
            _stprintf(szMessage, _T("The varResult is a IDispatch* by reference, = %p"), (*(rVarResult.ppdispVal)));
            break; 
         }

         //case VT_ARRAY|:                          //    SAFEARRAY           FAR* FAR* pparray;  
         //   //_stprintf(szMessage, _T("The varResult = %d"), rVarResult.);
         //  break; 

         case VT_BYREF|VT_VARIANT:                 //    VARIANT             FAR* pvarVal;       
         {
            logVar(CComVariant(*(rVarResult.pvarVal)), pTestOutput);
            break; 
         }

         // Generic ByRef.                         //    void                FAR* byref;         
         case VT_I1:                               //    char                cVal;               
         {
            _stprintf(szMessage, _T("The varResult is a char, = %c"), rVarResult.cVal);
            break; 
         }

         case VT_UI2:                              //    unsigned short      uiVal;              
         {
            _stprintf(szMessage, _T("The varResult is a unsigned short, = %u"), rVarResult.uiVal);
            break; 
         }

         case VT_UI4:                              //    unsigned long       ulVal;              
         {
            _stprintf(szMessage, _T("The varResult is a unsigned long, = %u"), rVarResult.ulVal);
            break; 
         }

         case VT_INT:                              //    int                 intVal;             
         {
            _stprintf(szMessage, _T("The varResult is a int, = %d"), rVarResult.intVal);
            break; 
         }

         case VT_UINT:                             //    unsigned int        uintVal;            
         {
            _stprintf(szMessage, _T("The varResult unsigned int, = %u"), rVarResult.uintVal);
            break; 
         }

         case VT_BYREF|VT_I1:                      //    char FAR *          pal;              
         {
            _stprintf(szMessage, _T("The varResult is a char*, = %s"), (*(rVarResult.pcVal)));
            break; 
         }

         case VT_BYREF|VT_UI2:                     //    unsigned short FAR* puiVal;             
         {
            _stprintf(szMessage, _T("The varResult is a unsigned short*, = %u"), (*(rVarResult.puintVal)));
            break; 
         }

         case VT_BYREF|VT_UI4:                     //    unsigned long FAR * pulVal;             
         {
            _stprintf(szMessage, _T("The varResult is a unsigned long*, = %u"), (*(rVarResult.pulVal)));
            break; 
         }

         case VT_BYREF|VT_INT:                     //    int FAR *           pintVal;            
         {
            _stprintf(szMessage, _T("The varResult is a int*, = %d"), (*(rVarResult.pintVal)));
            break; 
         }

         case VT_BYREF|VT_UINT:                    //    unsigned int FAR *  puintVal;           
         {
            _stprintf(szMessage, _T("The varResult is a unsigned int*, = %u"), (*(rVarResult.puintVal)));
            break; 
         }

         case VT_EMPTY:
         {
            break;
         }
         
         default:                                         
            ATLASSERT(false);
      }
 
      if (szMessage[0] != '\0')
      {
         pTestOutput->LogResult(_bstr_t(szMessage), VARIANT_FALSE);
      }
   }
   
   // {secret} 
   // Don't allow any copies to be made
	CPropertyTester(const CPropertyTester&);
   // {secret} 
   // Don't allow the assigment operator
	CPropertyTester& operator=(const CPropertyTester& rCPropertyTester);
   // {secret} 
   // Don't allow the equality operator
	bool operator==(const CPropertyTester& rCPropertyTester);

   // {secret}
   VARIANT_BOOL m_bVerbose;

   // {secret}
   GetPropertyInfoMap m_getPropertyInfoMap;
   // {secret}
   PutPropertyInfoMap m_putPropertyInfoMap;
}; 
	
#endif      // #define CPROPERTYTESTER_H_A2EFEBC1_921D_11d3_AC01_00508B0D0D6E

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions