//----------------------------------------------------------------------- // Microsoft OLE DB // // Copyright (C) 1997-2000 Microsoft Corporation // // @doc // // @module QUIKTEST.CPP | This test module performs minimum testing // of an OLE DB provider by calling each method in the API. // #include "MODStandard.hpp" //Standard headers to be precompiled in MODStandard.cpp #include "QuikTest.h" #include "ExtraLib.h" #include "msdasc.h" //IID_IDataInitialize #include "msdadc.h" //IID_IRowPosition #include //Needed for _getcwd (current working directory) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Module Values // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // {{ TCW_MODULE_GLOBALS DECLARE_MODULE_CLSID = { 0xca9539f1, 0xd59f, 0x11ce, { 0xa9, 0xda, 0x00, 0xaa, 0x00, 0x3e, 0x77, 0x8a }}; DECLARE_MODULE_NAME("Quiktest"); DECLARE_MODULE_OWNER("Microsoft"); DECLARE_MODULE_DESCRIP("OLE DB Quik Test"); DECLARE_MODULE_VERSION(810940912); // TCW_WizardVersion(2) // TCW_Automation(False) // }} TCW_MODULE_GLOBALS_END //---------------------------------------------------------------------- // @func Module level initialization routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems BOOL ModuleInit(CThisTestModule * pThisTestModule) { return CreateModInfo(pThisTestModule); } //---------------------------------------------------------------------- // @func Module level termination routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems BOOL ModuleTerminate(CThisTestModule * pThisTestModule) { return ReleaseModInfo(pThisTestModule); } //---------------------------------------------------------------------- //Prints the error messages when run as a stand-alone executable. // HRESULT OutputText(const WCHAR* pwszFmt, ...) { va_list marker; va_start(marker, pwszFmt); vwprintf(pwszFmt, marker); va_end(marker); return S_OK; } //OutputText //////////////////////////////////////////////////////////////////////// // CBaseError Implementation // //////////////////////////////////////////////////////////////////////// //This class has the IError interface. Below is the implementation of the //methods of the IError interface and methods specific to the CBaseError //class. This class will be used as the error object when quiktest is //run as a stand-alone executable. //Constructor for CBaseError. CBaseError::CBaseError() { //Errors m_cModErrors = 0; m_cCaseErrors = 0; m_cVarErrors = 0; //Warnings m_cModWarnings = 0; m_cCaseWarnings = 0; m_cVarWarnings = 0; m_ErrorLevel = HR_STRICT; m_ExpectedHr = NULL; m_ActualHr = NULL; m_cRef = 0; } //Destructor (virtual) for CBaseError. CBaseError::~CBaseError() { } //QI for a supported interface. STDMETHODIMP CBaseError::QueryInterface(REFIID riid, void **ppvObject) { if(ppvObject == NULL) return E_INVALIDARG; *ppvObject = NULL; if(riid == IID_IUnknown) *ppvObject = (IUnknown*)this; else if(riid == IID_IError) *ppvObject = (IError*)this; else return E_NOINTERFACE; ((IUnknown*)*ppvObject)->AddRef(); return S_OK; } //Add reference count. STDMETHODIMP_(DWORD) CBaseError::AddRef(void) { return InterlockedIncrement((LONG*)&m_cRef); } //Decrement the reference count. If it goes down to zero delete //this object. STDMETHODIMP_(DWORD) CBaseError::Release(void) { InterlockedDecrement((LONG*)&m_cRef); if(m_cRef == 0) { delete this; return 0; } return m_cRef; } STDMETHODIMP CBaseError::ResetModErrors(void) { m_cModErrors = 0; return S_OK; } STDMETHODIMP CBaseError::ResetModWarnings(void) { m_cModWarnings = 0; return S_OK; } STDMETHODIMP CBaseError::ResetCaseErrors(void) { m_cCaseErrors = 0; return S_OK; } STDMETHODIMP CBaseError::ResetCaseWarnings(void) { m_cCaseWarnings = 0; return S_OK; } STDMETHODIMP CBaseError::ResetVarErrors(void) { m_cVarErrors = 0; return S_OK; } STDMETHODIMP CBaseError::ResetVarWarnings(void) { m_cVarWarnings = 0; return S_OK; } STDMETHODIMP CBaseError::GetVarErrors(LONG *pdw) { *pdw = m_cVarErrors; return S_OK; } STDMETHODIMP CBaseError::GetVarWarnings(LONG *pdw) { *pdw = m_cVarWarnings; return S_OK; } STDMETHODIMP CBaseError::GetCaseErrors(LONG *pdw) { *pdw = m_cCaseErrors; return S_OK; } STDMETHODIMP CBaseError::GetCaseWarnings(LONG *pdw) { *pdw = m_cCaseWarnings; return S_OK; } STDMETHODIMP CBaseError::GetModErrors(LONG *pdw) { *pdw = m_cModErrors; return S_OK; } STDMETHODIMP CBaseError::GetModWarnings(LONG *pdw) { *pdw = m_cModWarnings; return S_OK; } STDMETHODIMP CBaseError::GetActualHr(LONG *pHR) { *pHR = m_ActualHr; return S_OK; } STDMETHODIMP CBaseError::SetErrorLevel(ERRORLEVEL eLevel) { m_ErrorLevel = eLevel; return S_OK; } STDMETHODIMP CBaseError::GetErrorLevel(ERRORLEVEL *pLevel) { *pLevel = m_ErrorLevel; return S_OK; } //Print the expected HRESULT. STDMETHODIMP CBaseError::LogExpectedHr(LONG hrExpected) { //Try to find the Error WCHAR* pwszError = GetErrorName(hrExpected); if(pwszError) return OutputText(L"\t\t%s %s\n", wszExpectedHR, pwszError); else return OutputText(L"\t\t%s 0x%08x\n", wszExpectedHR, hrExpected); } //Print the received HRESULT, file name, and line number. STDMETHODIMP CBaseError::LogReceivedHr(LONG hrExpected, BSTR bstrFile, LONG udwLine) { //Try to find the Error WCHAR* pwszError = GetErrorName(hrExpected); if(pwszError) OutputText(L"\t\t%s %s\n", wszReceivedHR, pwszError); else OutputText(L"\t\t%s 0x%08x\n", wszReceivedHR, hrExpected); //Print File and Line Number... return OutputText(L"\t\t%s %s %s %d\n\n", wszFile, bstrFile, wszLine, udwLine); } //Compare the actual HR with the expected HR and increment error or //warning count accordingly. Print appropriate message. STDMETHODIMP CBaseError::Validate( LONG ActualHr, BSTR bstrFile, LONG udwLine, LONG ExpectedHr, VARIANT_BOOL *pfResult) { //Record the HRESULT received by the function in question m_ActualHr = ActualHr; //Now we decide what to do about it switch (m_ErrorLevel) { case HR_OPTIONAL: //We don't care what the received result is *pfResult = TRUE; return S_OK; case HR_WARNING: //Expected must match received. case HR_STRICT: //NOTE: we differentiate between warning //and strict in Increment and Logxxxxx. if(ActualHr != ExpectedHr) { //Display the Header if(HR_WARNING == m_ErrorLevel) { Transmit((WCHAR*)wszWarningTitle); } else { Transmit((WCHAR*)wszErrorTitle); } //Log what we expected Increment(); LogExpectedHr(ExpectedHr); } else { *pfResult = TRUE; return S_OK; } break; case HR_SUCCEED: //Received result must be success code if(!SUCCEEDED(ActualHr)) { //Log what we expected OutputText(L"\t\t%s\n", wszExpectedSuccess); } else { *pfResult = TRUE; return S_OK; } break; case HR_FAIL: //Received result must be failure code if(!FAILED(ActualHr)) { //Log what we expected Transmit("Expected a Failing HRESULT\n"); } else { *pfResult = TRUE; return S_OK; } break; default: ASSERT(FALSE); } //If we got this far, the HRESULT received didn't match //what was expected, so log what was received and where LogReceivedHr(ActualHr, bstrFile, udwLine); *pfResult = FALSE; return S_OK; } //If objects compared were not equal, increment the error or warning //count. Print appropriate message. STDMETHODIMP CBaseError::Compare( VARIANT_BOOL fEqual, BSTR bstrFile, LONG udwLine, VARIANT_BOOL * pfResult) { //If the objects where not equal, increment error and print message if(!fEqual) { Increment(); OutputText(L"\t\t%s\n", wszCompareFailed); OutputText(L"\t\t%s %s %s %d\n\n", wszFile, bstrFile, wszLine, udwLine); } *pfResult = fEqual; return S_OK; } //Increment the error or warning counters. STDMETHODIMP CBaseError::Increment(void) { if(HR_WARNING == m_ErrorLevel) { //Increment all warning counters, from variation level on up m_cVarWarnings++; m_cCaseWarnings++; m_cModWarnings++; } else { //Increment all error counters, from variation level on up m_cVarErrors++; m_cCaseErrors++; m_cModErrors++; } return S_OK; } //Print text which is passed in as a CHAR* HRESULT CBaseError::Transmit(CHAR* pszString) { WCHAR* pwszString = NULL; pwszString = ConvertToWCHAR(pszString); OutputText(L"\t\t"); OutputText(pwszString); SAFE_FREE(pwszString); return S_OK; }; //Print text which is passed in as a BSTR. HRESULT CBaseError::Transmit(BSTR bstrString) { OutputText(L"\t\t"); return OutputText(bstrString); }; STDMETHODIMP CBaseError::Initialize(void) { return S_OK; } //////////////////////////////////////////////////////////////////////// // CQuickTest Class // //////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- // @class A base class used to do common work for all interface testcases, // such as verifying the interface is supported, and storage and cleanup of // interface pointers. It is assumed that any interfaces/objects obtained // by the user outside member functions are released by the user before // the next attempt to obtain new objects/interfaces via the member // functions. class CQuickTest : public CSessionObject { protected: //VARIABLES //@cmember DBPROP_SQLSUPPORT ULONG_PTR m_ulSQLSup; //@cmember Maximum number of open rows (DBPROP_MAXOPENROWS) ULONG_PTR m_ulMaxOpenRows; //@cmember Can Fetch bachwards (DBPROP_CANFETCHBACKWARDS) BOOL m_fFetchBackwards; //@cmember File name for persisted file WCHAR m_wszFile[2*PATH_SIZE]; //@cmember Number of property Info sets. ULONG m_cPropInfoSets; //@cmember Array of property Info Sets. DBPROPINFOSET* m_rgPropInfoSets; //@cmember Number of property ID sets. ULONG m_cPropIDSets; //@cmember Array of property ID Sets. DBPROPIDSET* m_rgPropIDSets; //@cmember URL to a rowset (the rowset dumped into the INI file). WCHAR* m_pwszRowsetURL; //@cmember Pointer to a CRowset object. CRowset* m_pCRowset; //INTERFACES //@cmember Pointer to IpersistFile interface IPersistFile* m_pIPersistFile; //@cmember Pointer to IDBProperties interface IDBProperties* m_pIDBProperties; //@cmember Pointer to IRowset interface IRowset* m_pIRowset; //@cmember Pointer to ICommand interface ICommand* m_pICommand; //@cmember Pointer to IBindResource (Binder) interface IBindResource* m_pIBindResource; //@cmember Pointer to IRow interface IRow* m_pIRow; private: //List of Provider types DBTYPE* m_rgProviderTypes; //Count of List of Provider types ULONG m_cProviderTypes; //@cmember Path to current working directory CHAR m_szPath[PATH_SIZE]; protected: //@cmember Constructor - Takes the derived TestCase name as parameter CQuickTest(LPWSTR wszTestCaseName); //[IN] Testcase Name //@cmember Destructor virtual ~CQuickTest(); //@cmember Saves object to file in current working directory HRESULT PersistToFile(); //@cmember Adds another DBPROPINFO or DBPROPINFOSET to the dynamic // array m_rgPropInfoSets. HRESULT SetPropInfo( DBPROPID propID, //[IN] Property ID const GUID& guidPropSet, //[IN] Property Set VARTYPE varType //[IN] Variant type ); //@cmember Adds another DBPROPID or DBPROPIDSET to the dynamic // array m_rgPropIDSets. HRESULT SetPropID( DBPROPID propID, //[IN] Property ID const GUID& guidPropSet //[IN] Property Set ); //@cmember Initializes m_rgPropIDSets and m_rgPropInfoSets with some // selected properties. void InitPropIDStructs(); //@cmember Set the flags of the given property info. BOOL SetFlags( DBPROPID propID, //[IN] Property ID const GUID& guidPropSet, //[IN] Property Set DBPROPFLAGS dwFlags //[IN] Prop Flags ); //@cmember Call GetPropertyInfo and sets the Flag of the properties // in m_rgPropInfoSets. This can be used later to check if // the property is supported. void InitSupInfo(); //@cmember Check if the I2 value is positive. Used for checking // value of DBPROP_INIT_PROMPT. BOOL checkPositive_I2(VARIANT* pv); //@cmember Wrapper for IRowset::GetNextRows. HRESULT GetNextRows( IRowset* pIRowset, //[IN] Pointer to rowset HCHAPTER* hChapter, //[IN] Handle to chapter DBROWOFFSET lRowsOffset, //[IN] Offset to row DBROWCOUNT cRows, //[IN] Number of rows to fetch DBCOUNTITEM* pcRowsObtained, //[OUT] Number of rows fetched HROW** prghRows //[OUT] Handle to fetched rows. ); //@cmember Wrapper for IRowset::ReleaseRows. HRESULT ReleaseRows( IRowset** ppIRowset, //[IN] Pointer to rowset DBCOUNTITEM* pcRows, //[IN] Num of rows to release HROW** prghRows //[IN] HROW of rows to release ); //@cmember Wrapper for IRowset::RestartPosition. HRESULT RestartPosition(IRowset* pIRowset) ; //@cmember Release the HACCESSOR and free the bindings. Release // IAccessor if pbReleaseIAcc is TRUE. HRESULT FreeAccessorAndBindings( IAccessor** ppIAccessor, //[IN] Pointer to IAccessor HACCESSOR* phAccessor, //[IN] Handle to accessor DBCOUNTITEM* pcBindings, //[IN] Number of bindings DBBINDING** prgBindings, //[IN] Binding Structs. BOOL pbReleaseIAcc=TRUE //[IN] Release IAccessor? ); //@cmember Append a property and its value to the Init String. HRESULT AppendToInitString( WCHAR** ppwszInitString, DBPROPID dwPropertyID, GUID guidPropertySet, VARIANT* pVariant ); //@cmember Generate a rowset (call OpenRowset) on the given table. HRESULT CreateOpenRowset( CTable* pTable, //[IN] Table on which to open the rowset. const IID& riid, //[IN] IID of requested interface on rowset. IUnknown** ppRowset, //[OUT] Pointer to rowset interface. IUnknown* pUnkOuter = NULL //[IN] For aggregation. ); //@cmember Verify the bindings obtained by GetBindings is same as // that used for creating the accessor. BOOL VerifyBindings( IAccessor* pIAccessor, //[IN] Pointer to IAccessor. HACCESSOR hAccessor, //[IN] handle to accessor DBCOUNTITEM cBindings, //[IN] Number of binding structs DBBINDING* rgBindings, //[IN] Binding structures DBACCESSORFLAGS dwCreateAccessorFlags //[IN] Value of Accessor flags used to create accessor ); //@cmember Fetch the specified rows, get their data and compare. BOOL GetDataAndCompare( DBROWOFFSET cSkipRows, //[IN] num of rows to skip. DBROWCOUNT cGetRows, //[IN] num of rows to fetch. DBCOUNTITEM numFirstRowInSet, //[IN] num of the first row in the set of rows to be fetched. DBORDINAL cColumns, //[IN] num of columns. DB_LORDINAL* rgColumnsOrd, //[IN] list of column ordinals. IRowset* pIRowset, //[IN] Pointer to IRowset. HACCESSOR hAccessor, //[IN] handle to accessor DBCOUNTITEM cBindings, //[IN] Number of bindings DBBINDING* rgBindings, //[IN] Binding structs DBLENGTH cbRowSize, //[IN] row size CTable* pTable = NULL //[IN] pointer to base table ); //@cmember Get the bookmark for the given row. BOOL GetBookmark( DBCOUNTITEM ulRow, //[IN] row number for which to get bookmark (1 based) DBLENGTH cbRowSize, //[IN] row size HACCESSOR hAccessor, //[IN] handle to accessor DBCOUNTITEM cBindings, //[IN] number of bindings DBBINDING* rgBindings, //[IN] binding structs IUnknown* pIUnkRowset, //[IN] pointer to the rowset DBBKMARK *pcbBookmark, //[OUT] size of bookmark BYTE **ppBookmark //[OUT] value of bookmark ); //@cmember Check if the two DBCOLUMNDESC are equal. BOOL CompareColumnDesc( DBCOLUMNDESC* pCD1, //[IN] column description DBCOLUMNDESC* pCD2 //[IN] column description ); //@cmember Get the supported DBTYPEs from CTable's CCol structs. void GetProviderTypes(CTable* pTable); //@cmember Check if a given Type exists in CTable's CCol structs. BOOL IsSupportedType(DBTYPE dwType); //@cmember Check if the given index exists in the given table. TESTRESULT DoesIndexExist( IDBSchemaRowset* pIDSR, //[IN] pointer to interface DBID* pTableID, //[IN] table ID DBID* pIndexID, //[IN] Index ID BOOL* pfExists //[OUT] does index exist ); //@cmember Get the available optional columns through IColumnsRowset. HRESULT GetAvailableColumns( IUnknown* pUnk, //[IN] Pointer to the object. DBORDINAL* pcOptCols, //[OUT] Number of optional columns. DBID** prgOptCols //[OUT] DBIDs of optional columns. ); //@cmember Check the list of optional metadata columns returned by // IColumnsRowset::GetAvailableColumns. BOOL CheckOptColumns( const DBORDINAL cOptCols, //[IN] num of optional columns const DBID* rgOptCols //[IN] array of optional columns ); //@cmember Check the columns rowset returned by IColumnsRowset:: // GetColumnsRowset. BOOL CheckColumnsRowset( IUnknown* pIUnk, //[IN] pointer to the columns rowset const DBORDINAL cOptCols, //[IN] num of optional columns const BOOL bOrgRowsetHasBookmark //[IN] does the original rowset have bookmark column ); //@cmember Create an instance of the Root Binder, requesting // IBindResource. Then QI for IDBBinderProperties and // set the initialization properties. BOOL CreateRootBinder(); //@cmember Test IDBProperties::Getproperties method. TESTRESULT testGetProperties(); //@cmember Test IDBProperties::Getproperties method with (0,NULL). TESTRESULT testGetAllProperties(IDBProperties* pIDBProp); //@cmember Test IDBProperties::GetPropertyInfo method. TESTRESULT testGetPropInfo(); //@cmember Test IDBProperties::GetPropertyInfo method with (0,NULL). TESTRESULT testGetAllPropInfo(IDBProperties* pIDBProp); //@cmember Test IDBProperties::SetProperties method (set to a valid // value). TESTRESULT testSetProperties1(); //@cmember Test IDBProperties::SetProperties method (set to VT_EMPTY) TESTRESULT testSetProperties2(); //@cmember Test GetProperties and GetPropertyInfo while DSO is // uninitialized. TESTRESULT testGetPropBeforeInit(); //@cmember Test IDBInfo::GetKeywords method. TESTRESULT testGetKeywords(); //@cmember Test IDBInfo::GetLiteralInfo method. TESTRESULT testGetLiteralInfo(); //@cmember Test ISourcesRowset interface. TESTRESULT testISrcRowset(); //@cmember Test IDataInitialize::CreateDBInstance method. TESTRESULT testIDataIzCreateDBIns(); //@cmember Test IDataInitialize::GetDataSource method. TESTRESULT testIDataIzGetDS(); //@cmember Test IGetDataSource::GetDataSource method. TESTRESULT testGetDataSource(); //@cmember Test IOpenRowset::OpenRowset method. TESTRESULT testOpenRowset(); //@cmember Test ISessionProperties::GetProperties method. TESTRESULT testSessGetProp(); //@cmember Test ISessionProperties::SetProperties method. TESTRESULT testSessSetProp(); //@cmember Test IDBCreateCommand interface. TESTRESULT testCreateCommand(); //@cmember Test IDBSchemaRowset::GetSchemas method. TESTRESULT testGetSchemas(); //@cmember Test the COLUMNS rowset obtained by calling // IDBSchemaRowset::GetRowset. TESTRESULT testColumnsSchemaRowset(); //@cmember Test the TABLES rowset obtained by calling // IDBSchemaRowset::GetRowset. TESTRESULT testTablesSchemaRowset(); //@cmember Test the PROVIDER_TYPES rowset obtained by calling // IDBSchemaRowset::GetRowset. TESTRESULT testProvTypesSchemaRowset(); //@cmember Test ITableDefinition::AddColumn method. TESTRESULT testAddColumn(); //@cmember Test ITableDefinition::CreateTable method. TESTRESULT testCreateTable(); //@cmember Test ITableDefinition::DropColumn method. TESTRESULT testDropColumn(); //@cmember Test ITableDefinition::DropTable method. TESTRESULT testDropTable(); //@cmember Test IIndexDefinition methods. TESTRESULT testIIndexDef(); //@cmember Test IAlterIndex::AlterIndex method. TESTRESULT testAlterIndex(); //@cmember Test IAlterTable::AlterColumn method. TESTRESULT testAlterColumn(); //@cmember Test IAlterTable::AlterTable method. TESTRESULT testAlterTable(); //@cmember Test ITableDefinitionWithConstraints::AddConstraint & DropConstraint methods. TESTRESULT testAddAndDropConstraint(); //@cmember Test ITableDefinitionWithConstraints::CreateTableWithConstraints method. TESTRESULT testCreateTableWithConstraints(); //@cmember Test aggregation of Session. TESTRESULT testAggregateSession(IDBCreateSession* pIDBCreateSession); //@cmember Test IConvertType method. TESTRESULT testIConvertType(); //@cmember Test IColumnsInfo::GetColumnInfo method. TESTRESULT testGetColumnInfo(IUnknown* pIUnknown); //@cmember Test IColumnsInfo::MapColumnIDs method. TESTRESULT testMapColumnIDs(IUnknown* pIUnknown); //@cmember Test the IAccessor interface methods. TESTRESULT testIAccessor(); //@cmember Test the IRowsetInfo::GetProperties method // or the ICommandProperties::GetProperties method. TESTRESULT testRowsetGetProp(IUnknown* pIUnknown); //@cmember Test the IRowsetInfo::GetReferencedRowset method TESTRESULT testIRowsetInfoGetRefRowset(); //@cmember Test the IRowsetInfo::GetSpecification method on a // rowset generated from Session. TESTRESULT testIRowsetInfoGetSpec(); //@cmember Test the IRowsetInfo::GetSpecification method on a // rowset generated from Command. TESTRESULT testIRowsetInfoGetSpecCmd(); //@cmember Test the IRowset (No props set) TESTRESULT testIRowset2(); //@cmember Test the IRowset (Scroll_Back and CANHOLDROWS set) TESTRESULT testIRowset3(); //@cmember Test the IRowsetLocate::Compare TESTRESULT testIRowsetLocateCompare(); //@cmember Test the IRowsetLocate::GetRowsAt TESTRESULT testIRowsetLocateGetRowsAt(); //@cmember Test the IRowsetLocate::GetRowsByBookmark TESTRESULT testIRowsetLocateGetRowsByBkm(); //@cmember Test the IRowsetLocate::Hash TESTRESULT testIRowsetLocateHash(); //@cmember Test the IRowsetFind::FindNextRow TESTRESULT testFindNextRow(); //@cmember Test the IRowsetScroll::GetApproximatePosition TESTRESULT testGetApproxPos(); //@cmember Test the IRowsetScroll::GetRowsAtRatio TESTRESULT testGetRowsAtRatio(); //@cmember Test the IRowPosition methods. TESTRESULT testIRowPosition(); //@cmember Test aggregation of Rowset. TESTRESULT testAggregateRowset(); //@cmember Test the IRowsetIdentity methods. TESTRESULT testIRowsetIdentity(); //@cmember Test the IRowset methods (various properties set) TESTRESULT testIRowset(); //@cmember Test the IRowsetChange::SetData method. TESTRESULT testIRowsetChangeSet(); //@cmember Test the IRowsetChange::DeleteRows method. TESTRESULT testIRowsetChangeDelete(); //@cmember Test the IRowsetChange::Insert method. TESTRESULT testIRowsetChangeInsert(); //@cmember Test the IRowsetUpdate interface. TESTRESULT testIRowsetUpdate(); //@cmember Test the IRowsetResynch methods. TESTRESULT testIRowsetResynch(); //@cmember Test the IRowsetRefresh methods. TESTRESULT testIRowsetRefresh(); //@cmember Test the IAccessor (Command interface) methods. TESTRESULT testCmdIAccessor(); //@cmember Test the ICommandProperties::SetProperties method. TESTRESULT testSetCmdProp(); //@cmember Test the ICommandText interface. TESTRESULT testICmdText(); //@cmember Test the ICommand::GetDBSession method. TESTRESULT testICmdGetDBSession(); //@cmember Test the ICommand::Execute method (set, exe, set, exe, // set, exe). TESTRESULT testICmdExec1(); //@cmember Test the ICommand::Execute method (set, prepare, exe, // exe, exe). TESTRESULT testICmdExec2(); //@cmember Test the ICommandPrepare::Prepare method. TESTRESULT testCmdPrep(); //@cmember Test the ICommandPrepare::UnPrepare method. TESTRESULT testCmdUnprep(); //@cmember Make the parameter bindings to be used in testICmdWParam. BOOL MakeParamBindings( CTable* pTable, DBORDINAL cColumnsOnTable, DBORDINAL* pcParamColMap, LONG_PTR* rgParamColMap, DB_UPARAMS* pcDbParamBindInfo, DBPARAMBINDINFO* rgDbParamBindInfo, DB_UPARAMS* rgParamOrdinals, DBCOLUMNINFO* rgTableInfo); //@cmember Test GetParameterInfo for ICommandWithParameters. TESTRESULT testGetParamInfo( ICommandWithParameters* pICWP, CTable* pTable, DB_UPARAMS cDbParamBindInfo, DBPARAMBINDINFO* rgDbParamBindInfo, LONG_PTR* rgParamColMap); //@cmember Test the ICommandWithParameters methods. TESTRESULT testICmdWParam(); //@cmember Test the IMultipleResults. TESTRESULT testIMultipleResults(); //@cmember Test the Error interfaces. TESTRESULT testIError(); //@cmember Test transaction commit (fRetaining=FALSE). TESTRESULT testTransactionCommit(); //@cmember Test transaction abort (fRetaining=FALSE). TESTRESULT testTransactionAbort(); //@cmember Test the Storage Object (ISequentialStream). TESTRESULT testStorageObj(); //@cmember Test the IRow methods. BOOL testIRow(IRow* pIRow, DBCOUNTITEM ulRowNum=0); //@cmember Test the IColumnsInfo methods on a Row object. If // bTestResColInfo is TRUE, then it also tests the // method GetRestrictedColumnInfo. BOOL testColInfo2( CRowObject* pCRowObj, BOOL bTestResColInfo = FALSE); //@cmember Test the IRowChange method SetColumns on a Row object. BOOL testIRowChange(CRowObject* pCRowObj); //@cmember Test the IRowSchemaChange methods on a Row object. BOOL testIRowSchemaChange(CRowObject* pCRowObj); }; //////////////////////////////////////////////////////////////////////// // CQuickTest Implementation // //////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------- // @mfunc Connection base class constructor, must take testcase name // as parameter. // CQuickTest::CQuickTest(LPWSTR wszName) //Takes TestCase name as parameter : CSessionObject(wszName) { //Empty file so we know it hasn't been set yet m_wszFile[0] = L'\0' ; m_szPath[0] = '\0'; m_cProviderTypes = 0; m_rgProviderTypes = NULL; m_pwszRowsetURL = NULL; m_pCRowset = NULL; m_ulSQLSup = 0; m_ulMaxOpenRows = 0; m_fFetchBackwards = FALSE; m_cPropSets = 0; m_cPropInfoSets = 0; m_cPropIDSets = 0; m_rgPropSets = NULL; m_rgPropInfoSets = NULL; m_rgPropIDSets = NULL; m_pIPersistFile = NULL; m_pIDBProperties = NULL; m_pIRowset = NULL; m_pICommand = NULL; m_pIBindResource = NULL; m_pIRow = NULL; } //---------------------------------------------------------------------- //@mfunc Destructor for CQuickTest class. // CQuickTest::~CQuickTest() { FreeProperties(&m_cPropSets, &m_rgPropSets); FreeProperties(&m_cPropInfoSets, &m_rgPropInfoSets); FreeProperties(&m_cPropIDSets, &m_rgPropIDSets); SAFE_FREE(m_rgProviderTypes); SAFE_FREE(m_pwszRowsetURL); //Release here if we haven't before SAFE_RELEASE(m_pIPersistFile); SAFE_RELEASE(m_pIDBProperties); SAFE_RELEASE(m_pIRowset); SAFE_RELEASE(m_pICommand); SAFE_RELEASE(m_pIBindResource); SAFE_RELEASE(m_pIRow); } //-------------------------------------------------------------------- // @mfunc Find the current working directory and use it to set // the path and file name for persisting files. Then attempt to // save to that file. An instance of CLocaleInfo is created temporarily, // only to use its member function 'MakeUnicodeIntlString'. // HRESULT CQuickTest::PersistToFile() { WCHAR wszSaveFile[2*PATH_SIZE]; HRESULT hr = E_FAIL; CLocaleInfo* pCLI=NULL; m_szPath[0] = '\0'; //If file is set, we've saved already, so just return NO_ERROR. if (m_wszFile[0] != L'\0') return NO_ERROR; //Get current working directory to be used for creating files if(!_getcwd(m_szPath,PATH_SIZE)) { odtLog << wszErrorFindingCurrentPath; return ResultFromScode(E_FAIL); } //Build whole file path and name MultiByteToWideChar(CP_ACP,0,(LPCSTR)m_szPath,-1,m_wszFile,PATH_SIZE); //For International strings. BOOL fIntl = FindIntlSetting(); if(!fIntl) wcscat(m_wszFile,L"\\QuikTest long file name.tst"); else { pCLI = new CLocaleInfo(GetUserDefaultLCID()); if(pCLI==NULL) goto CLEANUP; pCLI->MakeUnicodeIntlString(wszSaveFile, 16); wcscat(m_wszFile, L"\\"); wcscat(m_wszFile, wszSaveFile); wcscat(m_wszFile, L".tst"); } //Save to the specified file. hr = m_pIPersistFile->Save((LPOLESTR)m_wszFile,TRUE); if(hr != S_OK) m_wszFile[0] = L'\0'; CLEANUP: SAFE_DELETE(pCLI) return hr; } //PersistToFile //----------------------------------------------------------------------- //@mfunc Append another DBPROPINFO and/or DBPROPINFOSET to m_rgPropInfoSets //and increment the counter m_cPropInfoSets. The variant is left empty //and dwFlags is initalized to NOT_SUPPORTED. // HRESULT CQuickTest::SetPropInfo( DBPROPID propID, //[IN] Property ID const GUID& guidPropSet, //[IN] Property Set VARTYPE varType //[IN] Variant type ) { ASSERT(propID); ULONG cPropertyInfos = 0; DBPROPINFO* rgPropertyInfos = NULL; ULONG cPropInfoSets = m_cPropInfoSets; DBPROPINFOSET* rgPropInfoSets = m_rgPropInfoSets; //Find the propertyInfo Set in which to insert the new DBPROPINFO. ULONG iPropInfoSet = ULONG_MAX; for(ULONG i=0; iGetPropertyInfo(0,NULL,&cPropInfoSets, &rgPropInfoSets,NULL), S_OK)) goto CLEANUP; //At least CANHOLDROWS has to be supported. TESTC(cPropInfoSets !=0) TESTC(rgPropInfoSets !=NULL) for(iSet=0; iSetcPropertyInfos; iInfo++) { if(pSet->guidPropertySet==DBPROPSET_DATASOURCEINFO) { pInfo = &(pSet->rgPropertyInfos[iInfo]) ; switch(pInfo->dwPropertyID) { case DBPROP_ACTIVESESSIONS: COMPARE(SetFlags(DBPROP_ACTIVESESSIONS, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_CATALOGLOCATION: COMPARE(SetFlags(DBPROP_CATALOGLOCATION, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_COLUMNDEFINITION: COMPARE(SetFlags(DBPROP_COLUMNDEFINITION, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_DATASOURCENAME: COMPARE(SetFlags(DBPROP_DATASOURCENAME, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_DATASOURCEREADONLY: COMPARE(SetFlags(DBPROP_DATASOURCEREADONLY, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_DBMSNAME: COMPARE(SetFlags(DBPROP_DBMSNAME, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_DBMSVER: COMPARE(SetFlags(DBPROP_DBMSVER, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_IDENTIFIERCASE: COMPARE(SetFlags(DBPROP_IDENTIFIERCASE, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_MAXROWSIZE: COMPARE(SetFlags(DBPROP_MAXROWSIZE, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_MAXTABLESINSELECT: COMPARE(SetFlags(DBPROP_MAXTABLESINSELECT, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_PROVIDERNAME: COMPARE(SetFlags(DBPROP_PROVIDERNAME, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_QUOTEDIDENTIFIERCASE: COMPARE(SetFlags(DBPROP_QUOTEDIDENTIFIERCASE, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_ROWSETCONVERSIONSONCOMMAND: COMPARE(SetFlags(DBPROP_ROWSETCONVERSIONSONCOMMAND, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_SQLSUPPORT: COMPARE(SetFlags(DBPROP_SQLSUPPORT, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; case DBPROP_USERNAME: COMPARE(SetFlags(DBPROP_USERNAME, DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE); break; default: break; }//switch } else if(pSet->guidPropertySet==DBPROPSET_DBINIT) { pInfo = &(pSet->rgPropertyInfos[iInfo]) ; switch(pInfo->dwPropertyID) { case DBPROP_AUTH_PASSWORD: COMPARE(SetFlags(DBPROP_AUTH_PASSWORD, DBPROPSET_DBINIT, pInfo->dwFlags),TRUE); break; case DBPROP_AUTH_USERID: COMPARE(SetFlags(DBPROP_AUTH_USERID, DBPROPSET_DBINIT, pInfo->dwFlags),TRUE); break; case DBPROP_INIT_DATASOURCE: COMPARE(SetFlags(DBPROP_INIT_DATASOURCE, DBPROPSET_DBINIT, pInfo->dwFlags),TRUE); break; case DBPROP_INIT_LCID: COMPARE(SetFlags(DBPROP_INIT_LCID, DBPROPSET_DBINIT, pInfo->dwFlags),TRUE); break; case DBPROP_INIT_LOCATION: COMPARE(SetFlags(DBPROP_INIT_LOCATION, DBPROPSET_DBINIT, pInfo->dwFlags),TRUE); break; case DBPROP_INIT_MODE: COMPARE(SetFlags(DBPROP_INIT_MODE, DBPROPSET_DBINIT, pInfo->dwFlags),TRUE); break; case DBPROP_INIT_PROMPT: COMPARE(SetFlags(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT, pInfo->dwFlags),TRUE); break; case DBPROP_INIT_PROVIDERSTRING: COMPARE(SetFlags(DBPROP_INIT_PROVIDERSTRING, DBPROPSET_DBINIT, pInfo->dwFlags),TRUE); break; case DBPROP_INIT_TIMEOUT: COMPARE(SetFlags(DBPROP_INIT_TIMEOUT, DBPROPSET_DBINIT, pInfo->dwFlags),TRUE); break; default: break; }//switch } else if(pSet->guidPropertySet==DBPROPSET_ROWSET) { pInfo = &(pSet->rgPropertyInfos[iInfo]) ; switch(pInfo->dwPropertyID) { case DBPROP_CANHOLDROWS: COMPARE(SetFlags(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, pInfo->dwFlags),TRUE); break; default: break; }//switch } } } CLEANUP: FreeProperties(&cPropInfoSets, &rgPropInfoSets); return; } //InitSupInfo //---------------------------------------------------------------------- //@mfunc Verify that the VT_I2 variant has a non-negative value. // BOOL CQuickTest::checkPositive_I2(VARIANT* pv) { if((V_VT(pv) == VT_I2) && (V_I2(pv) >= 0)) return TRUE; else return FALSE; } //checkPositive_I2 //---------------------------------------------------------------------- //@mfunc Wrapper for IRowset::GetNextRows. // HRESULT CQuickTest::GetNextRows( IRowset* pIRowset, //[IN] Pointer to rowset HCHAPTER* hChapter, //[IN] Handle to chapter DBROWOFFSET lRowsOffset, //[IN] Offset to row DBROWCOUNT cRows, //[IN] Number of rows to fetch DBCOUNTITEM* pcRowsObtained, //[OUT] Number of rows fetched HROW** prghRows //[OUT] Handle to fetched rows. ) { DBCOUNTITEM cRowsObtained = NO_ROWS; DBCOUNTITEM i=0; HROW* rghRowsInput = NULL; HRESULT hr = S_OK; HRESULT hrRet = E_FAIL; TESTC(prghRows != NULL) TESTC(pcRowsObtained != NULL) TESTC(pIRowset != NULL) //Record if we passed in consumer allocated array... rghRowsInput = *prghRows; //Fetch the rows. hr = pIRowset->GetNextRows(NULL, lRowsOffset, cRows, &cRowsObtained, prghRows); //Verify correct values are returned if(hr == S_OK) { TESTC(cRowsObtained == (DBCOUNTITEM) ABS(cRows)); //Verify row array for(i=0; i0) { TESTC(*prghRows != NULL) TESTC(**prghRows != DB_NULL_HROW) } } //Verify output array, depending upon whether it is consumer or //provider allocated... if(rghRowsInput) { //This is a user allocated static array. //This had better not be nulled out by the provider, if non-null //on input. TESTC(*prghRows == rghRowsInput); } else { TESTC(cRowsObtained ? *prghRows != NULL : *prghRows == NULL); } hrRet = hr; CLEANUP: if(pcRowsObtained) *pcRowsObtained = cRowsObtained; return hrRet; } //GetNextRows //---------------------------------------------------------------------- //@mfunc Wrapper for IRowset::ReleaseRows. // HRESULT CQuickTest::ReleaseRows( IRowset** ppIRowset, //[IN] Pointer to rowset DBCOUNTITEM* pcRows, //[IN] Num of rows to release HROW** prghRows //[IN] HROW of rows to release ) { HRESULT hr=S_OK; if(ppIRowset==NULL || pcRows==NULL || prghRows==NULL) return E_FAIL; if(*ppIRowset && *prghRows) hr = (*ppIRowset)->ReleaseRows(*pcRows, *prghRows, NULL, NULL, NULL); *pcRows = 0; PROVIDER_FREE(*prghRows); //*prghRows = NULL return hr; } //ReleaseRows //---------------------------------------------------------------------- //@mfunc Wrapper for IRowset::RestartPosition. // HRESULT CQuickTest::RestartPosition(IRowset* pIRowset) { HRESULT hr = E_FAIL; TESTC(pIRowset != NULL) hr = pIRowset->RestartPosition(NULL); //Mask the hr. if(hr==DB_S_COMMANDREEXECUTED) { hr = S_OK; odtLog<ReleaseAccessor(*phAccessor, NULL); *phAccessor = DB_NULL_HACCESSOR; hr = FreeAccessorBindings(*pcBindings, *prgBindings); *pcBindings = 0; *prgBindings = NULL; if(bReleaseIAcc) SAFE_RELEASE(*ppIAccessor); return hr; } //FreeAccessorAndBindings //---------------------------------------------------------------------- //@mfunc Appends a property and its value to the Init String. Returns a //NULL if an error occurs. // HRESULT CQuickTest::AppendToInitString(WCHAR** ppwszInitString, DBPROPID dwPropertyID, GUID guidPropertySet, VARIANT* pVariant) { TBEGIN ASSERT(ppwszInitString); WCHAR wszBuffer[MAX_QUERY_LEN+100]; wszBuffer[0] = L'\0'; WCHAR* pwszNewString = NULL; HRESULT hr = S_OK; //Now get the Keyword and Value WCHAR* pwszKeyword = GetPropDesc(dwPropertyID, guidPropertySet, m_pIDBInitialize); TESTC_(hr = VariantToString(pVariant, wszBuffer, MAX_QUERY_LEN+100, FALSE),S_OK); //Don't neccessaryly need a value, "keyword=;", but we //do need a keyword. This should map to a non-NULL property description TESTC(pwszKeyword != NULL); //Add this to the String pwszNewString = CreateString(L"%s%s =", *ppwszInitString ? L";" : L"", pwszKeyword); hr = AppendString(ppwszInitString, pwszNewString); SAFE_FREE(pwszNewString); //We might need to quote the items if there is an embedded semi if(wcschr(wszBuffer, L';')) pwszNewString = CreateString(L"\"%s\"", wszBuffer); else pwszNewString = CreateString(L"%s", wszBuffer); hr = AppendString(ppwszInitString, pwszNewString); CLEANUP: SAFE_FREE(pwszKeyword); SAFE_FREE(pwszNewString); return hr; } //AppendToInitString //---------------------------------------------------------------------- //@mfunc Call OpenRowset and verify the returned IRowset. This method //implicity uses m_cPropSets/m_rgPropSets. So if you want particular //properties set, just simply set them before calling this method. // HRESULT CQuickTest::CreateOpenRowset( CTable* pTable, //[IN] Table on which to open the rowset. const IID& riid, //[IN] IID of requested interface on rowset. IUnknown** ppRowset, //[OUT] Pointer to rowset interface. IUnknown* pUnkOuter //[IN] For aggregation. ) { HRESULT hr = E_FAIL; DBID* pTableID = NULL; TESTC(pTable != NULL) TESTC(m_pIOpenRowset != NULL) pTableID = &(pTable->GetTableIDRef()) ; //Call OpenRowset hr = m_pIOpenRowset->OpenRowset(pUnkOuter,pTableID,NULL, riid,m_cPropSets,m_rgPropSets,ppRowset); if(hr==S_OK || hr==DB_S_ERRORSOCCURRED) { //Verify Usable Rowset if(ppRowset && riid!=IID_NULL) { TESTC(*ppRowset!=NULL) } //Verify no errors if(hr==S_OK) { TESTC(VerifyPropSetStatus(m_cPropSets, m_rgPropSets, DBPROPSTATUS_OK)) } if(riid==IID_NULL) { //Verify no rowset returned if(ppRowset) TESTC(*ppRowset==NULL) } } else //OpenRowset failed. { //Verify no rowset returned if(ppRowset) TESTC(*ppRowset==NULL) } CLEANUP: return hr; } //CreateOpenRowset //---------------------------------------------------------------------- // @mfunc This a test for IAccessor::GetBindings method. It checks if // GetBindings returns the same bindings array as the ones used to create // the accessor. // BOOL CQuickTest::VerifyBindings( IAccessor* pIAccessor, //[IN] Pointer to IAccessor. HACCESSOR hAccessor, //[IN] handle to accessor DBCOUNTITEM cBindings, //[IN] Number of binding structs DBBINDING* rgBindings, //[IN] Binding structures DBACCESSORFLAGS dwCreateAccessorFlags //[IN] Value of Accessor flags used to create accessor ) { BOOL bSuccess = FALSE; DBCOUNTITEM cGetBindings = 0; DBCOUNTITEM ulIndex=0; DBBINDING* pGetBind = NULL; DBBINDING* pBind = NULL; DBBINDING* rgGetBindings = NULL; DBACCESSORFLAGS dwGetAccessorFlags = 0; TESTC(pIAccessor != NULL) //Obtained the bindings. TESTC_(pIAccessor->GetBindings(hAccessor, &dwGetAccessorFlags, &cGetBindings, &rgGetBindings),S_OK) //Verify the Accessor Flags and number of bindings. COMPARE(dwGetAccessorFlags , dwCreateAccessorFlags); COMPARE(cGetBindings , cBindings); //Verify the binding stuctures. if (cGetBindings == 0) { //This is a null accessor, binding array should be null TESTC(rgGetBindings == NULL) } else { TESTC(cGetBindings != 0) TESTC(rgGetBindings != NULL) for(ulIndex=0; ulIndexdwPart , pBind->dwPart); COMPARE(pGetBind->iOrdinal , pBind->iOrdinal); COMPARE(pGetBind->wType , pBind->wType); COMPARE(pGetBind->eParamIO , pBind->eParamIO); COMPARE(pGetBind->pTypeInfo , pBind->pTypeInfo); //Precision and scale only apply for numeric and decimal //types and then only if VALUE is bound. if ((pBind->wType == DBTYPE_NUMERIC || pBind->wType == DBTYPE_DECIMAL || pBind->wType == DBTYPE_DBTIMESTAMP) && (pBind->dwPart & DBPART_VALUE)) { COMPARE(pGetBind->bPrecision , pBind->bPrecision); COMPARE(pGetBind->bScale , pBind->bScale); } //These only apply if value is bound if (pBind->dwPart & DBPART_VALUE) { COMPARE(pGetBind->obValue , pBind->obValue); COMPARE(pGetBind->cbMaxLen , pBind->cbMaxLen); } //These only apply if type is DBTYPE_UNKNOWN if ((pBind->wType == DBTYPE_IUNKNOWN) && (pGetBind->pObject != NULL)) { COMPARE(pGetBind->pObject->dwFlags , pBind->pObject->dwFlags) ; COMPARE(pGetBind->pObject->iid , pBind->pObject->iid); } //These only apply if length is bound if (pBind->dwPart & DBPART_LENGTH) COMPARE(pGetBind->obLength , pBind->obLength); //These only apply if status is bound if (pBind->dwPart & DBPART_STATUS) COMPARE(pGetBind->obStatus , pBind->obStatus); }//For Loop } //If we get here, we must have passed bSuccess = TRUE; CLEANUP: FreeAccessorBindings(cGetBindings, rgGetBindings); return bSuccess; } //VerifyBindings //----------------------------------------------------------------------- //@mfunc Get the specified rows. Obtain their data and verify it using the //function CompareData. Then release all the obtained rows. It is left to //the caller of this function to make sure that the rows asked for exist //and check (and set) the values of properties DBPROP_CANHOLDROWS and //DBPROP_MAXOPENROWS if required. This function does not call //RestartPosition. // BOOL CQuickTest::GetDataAndCompare( DBROWOFFSET cSkipRows, //[IN] num of rows to skip. DBROWCOUNT cGetRows, //[IN] num of rows to fetch. DBCOUNTITEM numFirstRowInSet, //[IN] num of the first row in the set of rows to be fetched. DBORDINAL cColumns, //[IN] num of columns. DB_LORDINAL* rgColumnsOrd, //[IN] list of column ordinals. IRowset* pIRowset, //[IN] Pointer to IRowset. HACCESSOR hAccessor, //[IN] handle to accessor DBCOUNTITEM cBindings, //[IN] Number of bindings DBBINDING* rgBindings, //[IN] Binding structs DBLENGTH cbRowSize, //[IN] row size CTable* pTable //[IN] pointer to base table ) { BOOL bSuccess = FALSE; DBCOUNTITEM ulIndex = 0; DBCOUNTITEM rowNum = 0; //Row number of row to be compared. DBCOUNTITEM cRowsObtained = 0; HRESULT hr = S_OK; BYTE* pData = NULL; HROW* rghRows = NULL; TESTC(pIRowset != NULL) if(pTable == NULL) pTable = m_pTable; TESTC(pTable != NULL) //Use IRowset to retrieve data TESTC_(GetNextRows(pIRowset, NULL, cSkipRows, cGetRows, &cRowsObtained, (HROW **)&rghRows), S_OK) TESTC(cRowsObtained == (DBCOUNTITEM) ABS(cGetRows)); //Allocate a new data buffer. SAFE_ALLOC(pData, BYTE, cbRowSize) for(ulIndex=0; ulIndexGetData(rghRows[ulIndex], hAccessor, pData),S_OK)) continue; //adjust the rowNum according to the fetch direction. if(cGetRows >= 0) rowNum = numFirstRowInSet+ulIndex; else rowNum = numFirstRowInSet-ulIndex; //Verify data value, length and status are what is expected. TESTC(CompareData(cColumns, rgColumnsOrd, rowNum, pData, cBindings, rgBindings, pTable, m_pIMalloc, PRIMARY, COMPARE_ONLY)) CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings, pData), S_OK); } bSuccess = TRUE; CLEANUP: SAFE_FREE(pData); CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); return bSuccess; } //GetDataAndCompare //---------------------------------------------------------------------- //@mfunc Get the bookmark for a given row number. Row nums are 1 based. //Memory allocated for bookmark is freed by caller of this function. // BOOL CQuickTest::GetBookmark( DBCOUNTITEM ulRow, //[IN] row number for which to get bookmark (1 based) DBLENGTH cbRowSize, //[IN] row size HACCESSOR hAccessor, //[IN] handle to accessor DBCOUNTITEM cBindings, //[IN] number of bindings DBBINDING* rgBindings, //[IN] binding structs IUnknown* pIUnkRowset, //[IN] pointer to the rowset DBBKMARK *pcbBookmark, //[OUT] size of bookmark BYTE **ppBookmark //[OUT] value of bookmark ) { BOOL bSuccess = FALSE; HRESULT hr = S_OK; HROW* rghRows = NULL; DBCOUNTITEM cRowsObtained = 0; DBBKMARK dwAddr = 0; IRowset* pIRowset = NULL; BYTE* pData = NULL; if(!pcbBookmark || !ppBookmark) return FALSE; //Row numbers are 1 based. if(ulRow < 1) return FALSE; //VerifyInterface if(!VerifyInterface(pIUnkRowset,IID_IRowset, ROWSET_INTERFACE,(IUnknown**)&pIRowset)) { odtLog<GetData(*rghRows, hAccessor, pData),S_OK) //make sure the 0 column is for bookmark TESTC(rgBindings[0].iOrdinal == 0) //get the starting pointer of the consumer's buffer dwAddr = (DBBKMARK) pData; //get the length of the bookmark *pcbBookmark = *((DBBKMARK *)(dwAddr+rgBindings[0].obLength)); //allocate memory for bookmark SAFE_ALLOC(*ppBookmark, BYTE, *pcbBookmark); if(!(*ppBookmark)) goto CLEANUP; //copy the value of the bookmark into the consumer's buffer memcpy(*ppBookmark, (void *)(dwAddr+rgBindings[0].obValue), (size_t)*pcbBookmark); bSuccess=TRUE; CLEANUP: if(!bSuccess) odtLog<pTypeInfo == newCD->pTypeInfo); TESTC(oldCD->ulColumnSize == newCD->ulColumnSize); TESTC(oldCD->wType == newCD->wType); TESTC(!IsNumericType(oldCD->wType) || oldCD->bPrecision == newCD->bPrecision); TESTC((oldCD->wType != DBTYPE_NUMERIC && oldCD->wType != DBTYPE_DECIMAL) || oldCD->bScale == newCD->bScale); TESTC(CompareDBID(oldCD->dbcid, newCD->dbcid)); //compare the properties TESTC(oldCD->cPropertySets == newCD->cPropertySets); for(cPropSet=0; cPropSetcPropertySets; cPropSet++) { pOldPropSet = &(oldCD->rgPropertySets[cPropSet]); pNewPropSet = &(newCD->rgPropertySets[cPropSet]); //compare the props in that prop set TESTC(pOldPropSet->guidPropertySet == pNewPropSet->guidPropertySet); TESTC(pOldPropSet->cProperties == pNewPropSet->cProperties); for(cProp = 0; cProp < pOldPropSet->cProperties; cProp++) { pOldProp = &(pOldPropSet->rgProperties[cProp]); pNewProp = &(pNewPropSet->rgProperties[cProp]); //there are no info for some of the properties if ( (pNewProp->dwPropertyID == DBPROP_COL_AUTOINCREMENT ) || (pNewProp->dwPropertyID == DBPROP_COL_DEFAULT ) || (pNewProp->dwPropertyID == DBPROP_COL_UNIQUE ) ) continue; TESTC(pOldProp->dwPropertyID == pNewProp->dwPropertyID); TESTC(CompareVariant(&(pOldProp->vValue), &(pNewProp->vValue))); } } bSuccess = TRUE; CLEANUP: return bSuccess; } //CompareColumnDesc //---------------------------------------------------------------------- //@mfunc Allocate memory for m_rgProviderTypes, and fill it with the //provider types obtained from the tables column info. Each time this //function is called, the caller has to free the memory for //m_rgProviderTypes. This func is used by IConvertType test. // void CQuickTest::GetProviderTypes(CTable* pTable) { DBORDINAL cColumns = 0; DBORDINAL iCol = 0; CCol colTmp; //If m_rgProviderTypes exists, then return. if(m_rgProviderTypes) return; cColumns = pTable->CountColumnsOnTable(); //Allocate memory for storing the provider types. SAFE_ALLOC(m_rgProviderTypes, DBTYPE, cColumns); m_cProviderTypes = (ULONG) cColumns; // small no. //Copy the provider types from the tables column info. for(iCol=0; iColGetColInfo(iCol+1, colTmp)) { m_rgProviderTypes[iCol] = colTmp.GetProviderType(); } } CLEANUP: return; } //GetProviderTypes //---------------------------------------------------------------------- //@mfunc Check if the given type is in the list of provider types //m_rgProviderTypes. This func is used by IConvertType test. // BOOL CQuickTest::IsSupportedType(DBTYPE dwType) { ULONG ulIndex = 0; if(m_rgProviderTypes == NULL) return FALSE; for(ulIndex=0; ulIndexGetSchemas(&cSchema, &prgSchemas, &prgRestrictions),S_OK) //Check to see if DBSCHEMA_INDEXES is supported for(ulIndex=0, bIsSchemaSupported=FALSE; ulIndexuName.pwszName); rgRestrictIndexes[4].vt = VT_BSTR; rgRestrictIndexes[4].bstrVal = SysAllocString(pTableID->uName.pwszName); //Get the Index schema rowset. TESTC_(hr = pIDSR->GetRowset(NULL, DBSCHEMA_INDEXES, cRest, rgRestrictIndexes, IID_IRowset, 0, NULL, (IUnknown**) &pIndexRowset),S_OK) TESTC(pIndexRowset != NULL) //Fetch rows. There should be only 1 row or no rows. hr = GetNextRows(pIndexRowset, 0, 0, 3, &cRowsObtained, &rghRows) ; if(FAILED(hr)) { CHECK(hr, S_OK); goto CLEANUP; //TEST_FAIL. } if(cRowsObtained == 0 && rghRows == NULL) { //Index does not exist. tTestResult = TEST_PASS; *pfExists = FALSE; goto CLEANUP; } if(cRowsObtained == 0 || rghRows == NULL) { //An error occurred. COMPARE(cRowsObtained, 1); COMPARE(rghRows != NULL, TRUE); tTestResult = TEST_FAIL; goto CLEANUP; } //If we got here, then Index exists. TESTC(cRowsObtained == 1 && rghRows) TESTC(*rghRows != DB_NULL_HROW) *pfExists = TRUE; tTestResult = TEST_PASS; CLEANUP: CHECK(ReleaseRows(&pIndexRowset, &cRowsObtained, &rghRows), S_OK); for(ulIndex=0; ulIndex<5; ulIndex++) VariantClear(&rgRestrictIndexes[ulIndex]); PROVIDER_FREE(prgSchemas); PROVIDER_FREE(prgRestrictions); SAFE_RELEASE(pIndexRowset); return tTestResult; } //DoesIndexExist //------------------------------------------------------------------- //@mfunc Get the optional columns through IColumnsRowset. // HRESULT CQuickTest::GetAvailableColumns( IUnknown* pUnk, //[IN] Pointer to the object. DBORDINAL* pcOptCols, //[OUT] Number of optional columns. DBID** prgOptCols //[OUT] DBIDs of optional columns. ) { HRESULT hrRet = E_FAIL; IColumnsRowset* pIColumnsRowset = NULL; HRESULT hr = pUnk->QueryInterface(IID_IColumnsRowset, (void **) &pIColumnsRowset); if(hr == E_NOINTERFACE) { odtLog<GetAvailableColumns(pcOptCols, prgOptCols), S_OK) if((*pcOptCols==0) && (*prgOptCols==NULL)) { //Issue a warning. COMPAREW(*pcOptCols, 1); odtLog<<"WARNING: No Optional Metadata columns were returned.\n"; } else { TESTC((*pcOptCols !=0) && (*prgOptCols !=NULL)) } CLEANUP: SAFE_RELEASE(pIColumnsRowset); return hrRet; } //GetAvailableColumns //---------------------------------------------------------------------- //@mfunc Check if there are any mandatory columns in the list of //columns returned by IColumnsRowset::GetAvailableColumns. // BOOL CQuickTest::CheckOptColumns( const DBORDINAL cOptCols, //[IN] num of optional columns const DBID* rgOptCols //[IN] array of optional columns ) { BOOL bSuccess = TRUE; DBORDINAL iOpt = 0; ULONG iMand = 0; //there are a fixed no. of mand cols // Check if a mandatory column was returned for(iOpt=0; iOptGetColInfo(iRow+ !bOrgRowsetHasBookmark, col), S_OK) //Get the row data. TESTC_(hr=pIRowset->GetData(rghRows[0],hAccessor, pData),S_OK) //Check the first 6 mandatory columns of this row. for(iBind=0; iBind < cBindings; iBind++) { if((iBind==0) && usBookmark) continue; //Grab one column. pColumn = (DATA *) (pData + rgBindings[iBind].obStatus); // Mandatory columns :- if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_IDNAME)) { if( (DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK ) { bStatus = TRUE; COMPARE(wcscmp(col.GetColName(), (WCHAR*)pColumn->bValue),0) ; } } else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_GUID)) { if( (DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK ) { bStatus = TRUE; COMPARE((col.GetColID())->uGuid.guid, *((GUID*)pColumn->bValue)) ; } } else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_PROPID)) { if( (DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK ) { bStatus = TRUE; COMPARE((col.GetColID())->uName.ulPropid, *((ULONG*)pColumn->bValue)) ; //propid is ULONG } } else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_NAME)) { if((DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK) { if(!COMPAREW(wcscmp(col.GetColName(), (WCHAR*)pColumn->bValue),0)) { odtLog<bValue<<"\n"; } } } else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_NUMBER)) { TESTC((DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK) COMPARE(*((ULONG*)pColumn->bValue) , iRow+ !bOrgRowsetHasBookmark); } else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_TYPE)) { TESTC((DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK) COMPARE(*((USHORT*)pColumn->bValue), col.GetProviderType()) ; } } ReleaseInputBindingsMemory(cBindings, rgBindings, pData); //This is used to check if at least one of the three columns //(DBCOLUMN_IDNAME, DBCOLUMN_GUID and DBCOLUMN_PROPID) has a //status of DBSTATUS_S_OK. TESTC(bStatus) RELEASEROW: CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); bStatus = FALSE; cTotalRows++; iRow++; } TESTC_(hr, DB_S_ENDOFROWSET) //Check the total number of rows fetched from the columns rowset. TESTC(cTotalRows == m_pTable->CountColumnsOnTable()+ bOrgRowsetHasBookmark) bSuccess = TRUE; CLEANUP: SAFE_FREE(pData); CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); PROVIDER_FREE(rgInfo); PROVIDER_FREE(pStrBuf); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowset); return bSuccess; } //CheckColumnsRowset //---------------------------------------------------------------------- //@mfunc Create an instance of the Root Binder, requesting IBindResource. //Then QI for IDBBinderProperties and set the initialization properties, //and some rowset properties. Then get the rowset URL from INI file. // BOOL CQuickTest::CreateRootBinder() { TBEGIN ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; IBindResource* pIBR = NULL; IDBBinderProperties* pIDBBProp = NULL; pIBR = GetModInfo()->GetRootBinder(); TESTC_PROVIDER(pIBR != NULL) if(GetModInfo()->GetParseObject()->GetURL(ROWSET_INTERFACE)) m_pwszRowsetURL = wcsDuplicate(GetModInfo()->GetParseObject()->GetURL(ROWSET_INTERFACE)); else if(GetModInfo()->GetRootURL()) m_pwszRowsetURL = wcsDuplicate(GetModInfo()->GetRootURL()); //There may not be an INI file, or the INI file may not have a //[URL] section. In these cases we would want to skip. TESTC_PROVIDER(m_pwszRowsetURL != NULL) //URLs are of the form "scheme:". Cannot have a valid URL //with less than 2 characters. TESTC(wcslen(m_pwszRowsetURL) > 1) TESTC(VerifyInterface(pIBR, IID_IBindResource, BINDER_INTERFACE,(IUnknown**)&m_pIBindResource)) TESTC(VerifyInterface(m_pIBindResource, IID_IDBBinderProperties, BINDER_INTERFACE,(IUnknown**)&pIDBBProp)) TESTC(GetInitProps(&cPropSets, &rgPropSets)) SetProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET, &cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET, &cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; //SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &cPropSets, // &rgPropSets) ; TESTC_(pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK) CLEANUP: FreeProperties(&cPropSets, &rgPropSets); SAFE_RELEASE(pIDBBProp); TRETURN } //CreateRootBinder //----------------------------------------------------------------------- //@mfunc Get the properties specified in the property ID sets created in //the function InitPropIDStructs. Check for the property ID and status of //returned property sets. For the properties which show NOTSUPPORTED, //verify that they are indeed not supported. // TESTRESULT CQuickTest::testGetProperties() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG ulSupported = 0; ULONG iSet=0, iProp=0 ; ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; if(m_pIDBProperties == NULL) { odtLog<GetProperties(m_cPropIDSets, m_rgPropIDSets, &cPropSets, &rgPropSets) ; if(hr==DB_E_ERRORSOCCURRED) { odtLog< 0) tTestResult = TEST_PASS; CLEANUP: FreeProperties(&cPropSets, &rgPropSets); return tTestResult; } //testGetProperties //---------------------------------------------------------------------- //@mfunc Get ALL properties supported by a provider. For the returned //properties, check if the status is DBPROPSTATUS_OK. For a bunch of //properties check if the variant type of the variant in DBPROP is the //same as property type or VT_EMPTY. // TESTRESULT CQuickTest::testGetAllProperties(IDBProperties* pIDBProperties) { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG iSet=0, iProp=0 ; ULONG cPropSets = 0; DBPROP* pProp = NULL; DBPROPSET* rgPropSets = NULL; if(pIDBProperties == NULL) { odtLog<GetProperties(0, NULL, &cPropSets, &rgPropSets), S_OK) //At least CANHOLDROWS has to be supported. TESTC((cPropSets != 0) && (rgPropSets != NULL)) //Check the DBPROP structures for certain selected properties in the //Data Source Information and Data Source Initialization groups. for(iSet=0; iSetdwStatus, DBPROPSTATUS_OK) ; //The variant type of the vValue field in DBPROP should //either match the type of the property, or VT_EMPTY. switch(pProp->dwPropertyID) { case DBPROP_ACTIVESESSIONS: case DBPROP_MAXROWSIZE: case DBPROP_MAXTABLESINSELECT: case DBPROP_SQLSUPPORT: COMPARE(VT_I4, V_VT(& pProp->vValue)) ; break; case DBPROP_CATALOGLOCATION: COMPARE(VT_I4, V_VT(& pProp->vValue)) ; COMPARE((V_I4(&pProp->vValue)==DBPROPVAL_CL_START || V_I4(&pProp->vValue)==DBPROPVAL_CL_END), TRUE) ; break; case DBPROP_COLUMNDEFINITION: COMPARE(VT_I4, V_VT(& pProp->vValue)) ; COMPARE((V_I4(&pProp->vValue)==0 || V_I4(&pProp->vValue)==DBPROPVAL_CD_NOTNULL), TRUE) ; break; case DBPROP_DATASOURCENAME: case DBPROP_DBMSNAME: case DBPROP_DBMSVER: case DBPROP_PROVIDERNAME: case DBPROP_USERNAME: COMPARE((VT_BSTR == V_VT(&pProp->vValue) || VT_EMPTY == V_VT(&pProp->vValue)),TRUE); //COMPARE(VT_BSTR, V_VT(& pProp->vValue)); COMPARE(CheckVariant(& pProp->vValue),TRUE); break; case DBPROP_DATASOURCEREADONLY: case DBPROP_ROWSETCONVERSIONSONCOMMAND: COMPARE(VT_BOOL, V_VT(& pProp->vValue)); COMPARE(CheckVariant(& pProp->vValue),TRUE); break; case DBPROP_IDENTIFIERCASE: COMPARE(VT_I4, V_VT(& pProp->vValue)); COMPARE((V_I4(&pProp->vValue)==DBPROPVAL_IC_UPPER || V_I4(&pProp->vValue)==DBPROPVAL_IC_LOWER || V_I4(&pProp->vValue)==DBPROPVAL_IC_SENSITIVE || V_I4(&pProp->vValue)==DBPROPVAL_IC_MIXED),TRUE); break; case DBPROP_QUOTEDIDENTIFIERCASE: COMPARE(VT_I4, V_VT(& pProp->vValue)); COMPARE((V_I4(&pProp->vValue)==DBPROPVAL_IC_UPPER || V_I4(&pProp->vValue)==DBPROPVAL_IC_LOWER || V_I4(&pProp->vValue)==DBPROPVAL_IC_SENSITIVE || V_I4(&pProp->vValue)==DBPROPVAL_IC_MIXED),TRUE); break; default: break; } } } //If property belongs to the Data Source Initialization group. else if(rgPropSets[iSet].guidPropertySet==DBPROPSET_DBINIT) { for(iProp=0; iPropdwStatus, DBPROPSTATUS_OK); //The variant type of the vValue field in DBPROP should //either match the type of the property, or VT_EMPTY. switch(pProp->dwPropertyID) { case DBPROP_AUTH_PASSWORD: case DBPROP_AUTH_USERID: case DBPROP_INIT_DATASOURCE: case DBPROP_INIT_LOCATION: case DBPROP_INIT_PROVIDERSTRING: COMPARE((VT_BSTR == V_VT(&pProp->vValue) || VT_EMPTY == V_VT(&pProp->vValue)),TRUE); if(VT_EMPTY != V_VT(&pProp->vValue)) COMPARE(CheckVariant(&pProp->vValue),TRUE); break; case DBPROP_INIT_LCID: case DBPROP_INIT_MODE: case DBPROP_INIT_TIMEOUT: COMPARE((VT_I4 == V_VT(&pProp->vValue) || VT_EMPTY == V_VT(&pProp->vValue)),TRUE); break; case DBPROP_INIT_PROMPT: COMPARE((VT_I2 == V_VT(&pProp->vValue) || VT_EMPTY == V_VT(&pProp->vValue)),TRUE); if(VT_EMPTY != V_VT(&pProp->vValue)) COMPARE(checkPositive_I2(&pProp->vValue),TRUE); break; default: break; } } } //for any other property sets (and provider specific sets) else { for(iProp=0; iPropdwStatus, DBPROPSTATUS_OK); //Check the variant value for some variant types. COMPARE(CheckVariant(&pProp->vValue), TRUE); } } } tTestResult = TEST_PASS; CLEANUP: FreeProperties(&cPropSets, &rgPropSets); return tTestResult; } //testGetAllProperties //---------------------------------------------------------------------- //@mfunc Get the property info for the property ID sets created in //the function InitPropIDStructs. Check the property ID and flags of //returned property Info sets. // TESTRESULT CQuickTest::testGetPropInfo() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG iSet=0, iInfo=0 ; ULONG cPropInfoSets = 0; DBPROPINFOSET * rgPropInfoSets = NULL; WCHAR* pwszStringBuffer = NULL; if(m_pIDBProperties == NULL) { odtLog<GetPropertyInfo(m_cPropIDSets, m_rgPropIDSets, &cPropInfoSets, &rgPropInfoSets, &pwszStringBuffer) ; if(hr==DB_E_ERRORSOCCURRED) { odtLog<GetPropertyInfo(0, NULL, &cPropInfoSets, &rgPropInfoSets, &pwszStringBuffer), S_OK) //At least CANHOLDROWS has to be supported. TESTC((cPropInfoSets!=0) && (rgPropInfoSets!=NULL)) //for all property info sets... for(iSet=0; iSetdwFlags & DBPROPFLAGS_DATASOURCEINFO), DBPROPFLAGS_DATASOURCEINFO); //Verify description exists. COMPARE((wcslen(pPropInfo->pwszDescription)>0),TRUE); //Check if the variant type in DBPROPINFO matches that of //the property. switch(pPropInfo->dwPropertyID) { case DBPROP_ACTIVESESSIONS: case DBPROP_CATALOGLOCATION: case DBPROP_COLUMNDEFINITION: case DBPROP_IDENTIFIERCASE: case DBPROP_MAXROWSIZE: case DBPROP_MAXTABLESINSELECT: case DBPROP_QUOTEDIDENTIFIERCASE: case DBPROP_SQLSUPPORT: COMPARE(VT_I4, pPropInfo->vtType); break; case DBPROP_DATASOURCENAME: case DBPROP_DBMSNAME: case DBPROP_DBMSVER: case DBPROP_PROVIDERNAME: case DBPROP_USERNAME: COMPARE(VT_BSTR, pPropInfo->vtType); break; case DBPROP_DATASOURCEREADONLY: case DBPROP_ROWSETCONVERSIONSONCOMMAND: COMPARE(VT_BOOL, pPropInfo->vtType); break; default: break; } } } //If property belongs to the Data Source Initialization group. else if(rgPropInfoSets[iSet].guidPropertySet==DBPROPSET_DBINIT) { for(iInfo=0; iInfodwFlags & DBPROPFLAGS_DBINIT) , DBPROPFLAGS_DBINIT); //Verify description exists. COMPARE((wcslen(pPropInfo->pwszDescription)>0),TRUE); //Check if the variant type in DBPROPINFO matches that of //the property. switch(pPropInfo->dwPropertyID) { case DBPROP_AUTH_PASSWORD: case DBPROP_AUTH_USERID: case DBPROP_INIT_DATASOURCE: case DBPROP_INIT_LOCATION: case DBPROP_INIT_PROVIDERSTRING: COMPARE(VT_BSTR, pPropInfo->vtType); break; case DBPROP_INIT_LCID: case DBPROP_INIT_MODE: case DBPROP_INIT_TIMEOUT: COMPARE(VT_I4, pPropInfo->vtType); break; case DBPROP_INIT_PROMPT: COMPARE(VT_I2, pPropInfo->vtType); break; default: break; } } } //for other property groups (and provider specific groups) else { for(iInfo=0; iInfo0),TRUE); } } tTestResult = TEST_PASS; CLEANUP: FreeProperties(&cPropInfoSets, &rgPropInfoSets, &pwszStringBuffer); return tTestResult; } //testGetAllPropInfo //---------------------------------------------------------------------- //@mfunc Set the property DBPROP_INIT_PROMPT to DBPROMPT_NOPROMPT and //DBPROP_INIT_ASYNCH to 0. Then call GetProperty to verify. // TESTRESULT CQuickTest::testSetProperties1() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG ulSupported = 0; SHORT sPrompt = DBPROMPT_NOPROMPT; LONG lAsynch = 0; ULONG cPropSetsEx=0; DBPROPSET* rgPropSetsEx = NULL; IDBInitialize* pIDBInitialize = NULL; IDBProperties* pIDBProperties = NULL; //Initialize the variant to pass as an [OUT] parameter to GetProperty. VARIANT vVar; VariantInit(&vVar); VARIANT vVar2; VariantInit(&vVar2); //Create a new DSO. TESTC_(hr = GetModInfo()->CreateProvider(NULL, IID_IDBInitialize, (IUnknown**)&pIDBInitialize), S_OK) if(pIDBInitialize==NULL) { odtLog<SetProperties(cPropSetsEx, rgPropSetsEx), S_OK) //Set the 2 properties. FreeProperties(&m_cPropSets, &m_rgPropSets); SetProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT, &m_cPropSets, &m_rgPropSets, (void*)sPrompt, DBTYPE_I2); SetProperty(DBPROP_INIT_ASYNCH, DBPROPSET_DBINIT, &m_cPropSets, &m_rgPropSets, (void*)(LONG_PTR)lAsynch, DBTYPE_I4); //cast modified //Call SetProperties method. hr = pIDBProperties->SetProperties(m_cPropSets, m_rgPropSets); //check status. if(hr==S_OK) { //Status should be OK for both properties. COMPARE(m_rgPropSets[0].rgProperties[0].dwStatus, DBPROPSTATUS_OK); COMPARE(m_rgPropSets[0].rgProperties[1].dwStatus, DBPROPSTATUS_OK); } else if(hr==DB_S_ERRORSOCCURRED) { //If the status was not OK, then make sure the property was //not supported or settable. if(m_rgPropSets[0].rgProperties[0].dwStatus != DBPROPSTATUS_OK) { COMPARE(SettableProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT), FALSE); } else { ulSupported++; } if(m_rgPropSets[0].rgProperties[1].dwStatus != DBPROPSTATUS_OK) { COMPARE(SettableProperty(DBPROP_INIT_ASYNCH, DBPROPSET_DBINIT), FALSE); } else { ulSupported++; } } else { //Both properties were not supported or settable. TESTC_(hr, DB_E_ERRORSOCCURRED) COMPARE(SettableProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT), FALSE); COMPARE(SettableProperty(DBPROP_INIT_ASYNCH, DBPROPSET_DBINIT), FALSE); odtLog<Initialize(), S_OK); if(hr != S_OK) goto CLEANUP; tTestResult = TEST_PASS; CLEANUP: VariantClear(&vVar); VariantClear(&vVar2); FreeProperties(&cPropSetsEx, &rgPropSetsEx); FreeProperties(&m_cPropSets, &m_rgPropSets); //Release the DSO. SAFE_RELEASE(pIDBProperties); SAFE_RELEASE(pIDBInitialize); return tTestResult; } //testSetProperties1 //----------------------------------------------------------------------- //@mfunc Set the variant of properties DBPROP_INIT_PROMPT and //DBPROP_INIT_ASYNCH to VT_EMPTY. When SetProperties is called, //these should be set to their default values. Call GetProperty to //verify. // TESTRESULT CQuickTest::testSetProperties2() { TESTRESULT tTestResult = TEST_FAIL; //Test Return Value HRESULT hr = S_OK; ULONG ulSupported = 0; ULONG cPropSets = 1; DBPROPSET rgPropSets[1]; ULONG cPropSetsEx=0; DBPROPSET* rgPropSetsEx = NULL; DBPROP dwProp[2]; IDBInitialize* pIDBInitialize = NULL; IDBProperties* pIDBProperties = NULL; //Initialize the variant to pass as an [OUT] parameter to GetProperty. VARIANT vVar; VariantInit(&vVar); VARIANT vVar2; VariantInit(&vVar2); //Create a new DSO. TESTC_(hr = GetModInfo()->CreateProvider(NULL, IID_IDBInitialize, (IUnknown**)&pIDBInitialize), S_OK) if(pIDBInitialize==NULL) { odtLog<SetProperties(cPropSetsEx, rgPropSetsEx), S_OK) //Set DBPROP for PROMPT. memset(&dwProp[0], 0, sizeof(DBPROP)) ; dwProp[0].dwPropertyID = DBPROP_INIT_PROMPT; dwProp[0].dwOptions = DBPROPOPTIONS_REQUIRED; VariantInit(&dwProp[0].vValue); //Set DBPROP for ASYNCH. memset(&dwProp[1], 0, sizeof(DBPROP)) ; dwProp[1].dwPropertyID = DBPROP_INIT_ASYNCH; dwProp[1].dwOptions = DBPROPOPTIONS_REQUIRED; VariantInit(&dwProp[1].vValue); //Set the DBPROPSET. rgPropSets[0].rgProperties = dwProp; rgPropSets[0].cProperties = 2; rgPropSets[0].guidPropertySet = DBPROPSET_DBINIT; //Call SetProperties method. hr = pIDBProperties->SetProperties(cPropSets, rgPropSets); //check status. if(hr==S_OK) { //status should be OK for both props. COMPARE(rgPropSets[0].rgProperties[0].dwStatus, DBPROPSTATUS_OK); COMPARE(rgPropSets[0].rgProperties[1].dwStatus, DBPROPSTATUS_OK); } else if(hr==DB_S_ERRORSOCCURRED) { //if status is not OK, then make sure the property was not //supported or settable. if(rgPropSets[0].rgProperties[0].dwStatus != DBPROPSTATUS_OK) { COMPARE(SettableProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT), FALSE); } else { ulSupported++; } if(rgPropSets[0].rgProperties[1].dwStatus != DBPROPSTATUS_OK) { COMPARE(SettableProperty(DBPROP_INIT_ASYNCH, DBPROPSET_DBINIT), FALSE); } else { ulSupported++; } } else { //Both properties were not supported or settable. TESTC_(hr, DB_E_ERRORSOCCURRED) COMPARE(SettableProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT), FALSE); COMPARE(SettableProperty(DBPROP_INIT_ASYNCH, DBPROPSET_DBINIT), FALSE); odtLog<= 0 , TRUE); } //Initialize the DSO. CHECK(hr = pIDBInitialize->Initialize(), S_OK); if(hr != S_OK) goto CLEANUP; tTestResult = TEST_PASS; CLEANUP: VariantClear(&vVar); VariantClear(&vVar2); FreeProperties(&cPropSetsEx, &rgPropSetsEx); //Release the DSO. SAFE_RELEASE(pIDBProperties); SAFE_RELEASE(pIDBInitialize); return tTestResult; } //testSetProperties2 //---------------------------------------------------------------------- //@mfunc Test the GetProperties and GetPropertyInfo methods when the DSO //is in Uninitialized state. // TESTRESULT CQuickTest::testGetPropBeforeInit() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; IDBProperties* pIDBProp = NULL; //Create a new DSO. TESTC_(hr = GetModInfo()->CreateProvider(NULL, IID_IDBProperties, (IUnknown**)&pIDBProp), S_OK) if(pIDBProp==NULL) { odtLog<GetKeywords(&pwszKeywords), S_OK) if(!pwszKeywords) { //Issue a warning. odtLog< for pwszKeywords." <GetLiteralInfo(0, NULL, &cLiteralInfo, &rgLiteralInfo, &pCharBuffer), S_OK) if((cLiteralInfo==0) && (rgLiteralInfo==NULL)) { //Issue a warning. odtLog< 0, TRUE); tTestResult = TEST_PASS; goto CLEANUP; } TESTC((cLiteralInfo !=0) && (rgLiteralInfo !=NULL)) // Count the supported Literals for(ulIndex=0; ulIndex < cLiteralInfo; ulIndex++) if(rgLiteralInfo[ulIndex].fSupported) ulSupported++; //All the fSupported flags should have been TRUE. COMPARE(cLiteralInfo, ulSupported); // Check the pCharBuffer COMPARE(!pCharBuffer, NULL); // Check the Data returned for(ulIndex=0; ulIndex < cLiteralInfo; ulIndex++) { // These are the only 8 that should modify pwszLiteralValue and cchMaxLen, // and not modify pwszInvalidChar and pwszInvalidStartingChar. if( (rgLiteralInfo[ulIndex].lt == DBLITERAL_CATALOG_SEPARATOR) || (rgLiteralInfo[ulIndex].lt == DBLITERAL_ESCAPE_PERCENT_PREFIX)|| (rgLiteralInfo[ulIndex].lt == DBLITERAL_ESCAPE_PERCENT_SUFFIX)|| (rgLiteralInfo[ulIndex].lt == DBLITERAL_ESCAPE_UNDERSCORE_PREFIX)|| (rgLiteralInfo[ulIndex].lt == DBLITERAL_ESCAPE_UNDERSCORE_SUFFIX)|| (rgLiteralInfo[ulIndex].lt == DBLITERAL_LIKE_PERCENT) || (rgLiteralInfo[ulIndex].lt == DBLITERAL_LIKE_UNDERSCORE) || (rgLiteralInfo[ulIndex].lt == DBLITERAL_QUOTE_PREFIX) || (rgLiteralInfo[ulIndex].lt == DBLITERAL_QUOTE_SUFFIX) || (rgLiteralInfo[ulIndex].lt == DBLITERAL_SCHEMA_SEPARATOR) ) { // Check pwszLiteralValue exceptions if(!rgLiteralInfo[ulIndex].pwszLiteralValue) { odtLog<GetSourcesRowset(NULL, IID_IColumnsInfo, 0, NULL, (IUnknown **) &pICI), S_OK) TESTC(VerifyInterface(pICI,IID_IRowset, ROWSET_INTERFACE,(IUnknown**)&pIRowset)) TESTC(VerifyInterface(pICI,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) TESTC_(pICI->GetColumnInfo(&cColumns, &rgInfo, &pStringsBuffer), S_OK) // Check to see if the Bookmark Property is on if (rgInfo[0].iOrdinal == 0) { COMPARE(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, pICI), TRUE); usBkmExists = 1; } //Skip bookmark column, check each column info. //For each column check the position, column name and type. for(cCol=0; cColGetData(rghRows[0],hAccessor,pData), S_OK) cTotalRows++; //Get name, description and type of the source. pwszSourceParseName = (WCHAR*)(pData + rgBindings[1].obValue) ; usSourceType = *(USHORT*)(pData + rgBindings[3].obValue) ; TESTC(wcslen(pwszSourceParseName) > 0) TESTC(usSourceType==DBSOURCETYPE_DATASOURCE || usSourceType==DBSOURCETYPE_ENUMERATOR || usSourceType==DBSOURCETYPE_DATASOURCE_TDP || usSourceType==DBSOURCETYPE_DATASOURCE_MDP ) //Release the row handle CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); ReleaseInputBindingsMemory(cBindings, rgBindings, pData); }//while ends. odtLog<= 1) tTestResult = TEST_PASS; CLEANUP: SAFE_FREE(pData); CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); PROVIDER_FREE(rgInfo); PROVIDER_FREE(pStringsBuffer); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pICI); SAFE_RELEASE(pISR); return tTestResult; } //testISrcRowset //---------------------------------------------------------------------- //@mfunc Create a data source object using IDataInitialize::CreateDBInstance //and verify it. // TESTRESULT CQuickTest::testIDataIzCreateDBIns() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; CLSID clsidProv, clsid; ULONG cPropInfoSets = 0; DBPROPINFOSET* rgPropInfoSets = NULL; IDataInitialize* pIDI = NULL; IDBInitialize* pIDBI = NULL; IDBProperties* pIDBProperties = NULL; IPersist* pIPersist = NULL; hr = CoCreateInstance(CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SERVER, IID_IDataInitialize, (void**)&pIDI) ; if(hr != S_OK) { TESTC(!pIDI) odtLog<GetThisTestModule()->m_ProviderClsid ; //Create the DSO. Request IDBInitialize. TESTC_(hr = pIDI->CreateDBInstance(clsidProv, NULL, CLSCTX_INPROC_SERVER, NULL, IID_IDBInitialize, (IUnknown**)&pIDBI), S_OK) TESTC(pIDBI != NULL) //Get IDBProperties. TESTC(VerifyInterface(pIDBI,IID_IDBProperties, DATASOURCE_INTERFACE,(IUnknown**)&pIDBProperties)) TESTC(pIDBProperties != NULL) FreeProperties(&m_cPropSets, &m_rgPropSets); //Obtain Required Init Properties (from the Init String) TESTC(GetModInfo()->GetInitProps(&m_cPropSets, &m_rgPropSets)) //Set the Init properties. TESTC_(hr = pIDBProperties->SetProperties(m_cPropSets, m_rgPropSets), S_OK) //Initialize the DSO. TESTC_(hr = pIDBI->Initialize(), S_OK) //GetPropertyInfo. TESTC_(hr = pIDBProperties->GetPropertyInfo(0, NULL, &cPropInfoSets, &rgPropInfoSets, NULL), S_OK) if(cPropInfoSets == 0 && rgPropInfoSets == NULL) { odtLog< 0 && rgPropInfoSets != NULL) } //Create another DSO. This time request IPersist. TESTC_(hr = pIDI->CreateDBInstance(clsidProv, NULL, CLSCTX_INPROC_SERVER, NULL, IID_IPersist, (IUnknown**)&pIPersist), S_OK) TESTC(pIPersist != NULL) //Get class ID and verify that CLSID returned is identical to //the Provider CLSID. TESTC_(pIPersist->GetClassID(&clsid), S_OK) TESTC(clsid == GetModInfo()->GetThisTestModule()->m_ProviderClsid) tTestResult = TEST_PASS; CLEANUP: FreeProperties(&m_cPropSets, &m_rgPropSets); FreeProperties(&cPropInfoSets, &rgPropInfoSets); SAFE_RELEASE(pIDBI); SAFE_RELEASE(pIDBProperties); SAFE_RELEASE(pIPersist); SAFE_RELEASE(pIDI); return tTestResult; } //testIDataIzCreateDBIns //---------------------------------------------------------------------- //@mfunc Construct an initialization string from the init properties and //pass that in to IDataInitialize::GetDataSource. Check the obtained DSO. //Then call ::GetInitializationString (requesting password) and make sure //it contains the password. // TESTRESULT CQuickTest::testIDataIzGetDS() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG i, j; CLSID clsid; BOOL bDefault = FALSE; DBPROPSET* pPropSet = NULL; DBPROP* pProp = NULL; ULONG cPropInfoSets = 0; DBPROPINFOSET* rgPropInfoSets = NULL; ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; WCHAR* pwszProgID = NULL; WCHAR* pwszInitStr1 = NULL; WCHAR* pwszInitStr2 = NULL; WCHAR* pwszInitString = NULL; WCHAR* pwszValue = NULL; WCHAR* pwszValue1 = NULL; WCHAR* pwszDefPassword = NULL; IDataInitialize* pIDI = NULL; IDBInitialize* pIDBI = NULL; IDBProperties* pIDBProperties = NULL; IUnknown* pIUnknown = NULL; hr = CoCreateInstance(CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SERVER, IID_IDataInitialize, (void**)&pIDI) ; if(hr != S_OK) { TESTC(!pIDI) odtLog<GetInitProps(&cPropSets, &rgPropSets)) //Required for the function SetSupportedProperty. g_pIDBInitialize = m_pIDBInitialize ; //Required for obtaining the Password. This will be added //to the init string. If this property is not supported, //then the password will be visible anyway. SetSettableProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, DBPROPSET_DBINIT, &cPropSets, &rgPropSets) ; clsid = GetModInfo()->GetThisTestModule()->m_ProviderClsid ; TESTC_(ProgIDFromCLSID(clsid, &pwszProgID),S_OK); //Add the provider keyword and value to Init string. pwszInitString = CreateString(L"Provider = %s; ", pwszProgID); //Loop through specified properties and construct the String for(i=0; icProperties; j++) { pProp = &pPropSet->rgProperties[j]; //Now Add this Property AppendToInitString(&pwszInitString, pProp->dwPropertyID, pPropSet->guidPropertySet, &pProp->vValue); TESTC(pwszInitString != NULL); } } //If no properties, just use an empty string, since GetDataSource //fails on NULL AppendString(&pwszInitString, cPropSets ? L";" : L""); TESTC(pwszInitString != NULL) odtLog<GetDataSource(NULL, CLSCTX_INPROC_SERVER, pwszInitString, IID_IDBInitialize, (IUnknown**) &pIDBI), S_OK) TESTC(pIDBI != NULL) //Call Initilize(). TESTC_(hr = pIDBI->Initialize(), S_OK) //Get IDBProperties. TESTC(VerifyInterface(pIDBI,IID_IDBProperties, DATASOURCE_INTERFACE,(IUnknown**)&pIDBProperties)) TESTC(pIDBProperties != NULL) //Call GetPropertyInfo. TESTC_(hr = pIDBProperties->GetPropertyInfo(0, NULL, &cPropInfoSets, &rgPropInfoSets, NULL), S_OK) //Check returned values. if(cPropInfoSets == 0 && rgPropInfoSets == NULL) { COMPAREW(cPropInfoSets, 1); odtLog< 0 && rgPropInfoSets != NULL) } //Call GetInitializationString with fIncludePassword=TRUE. TESTC_(hr = pIDI->GetInitializationString((IUnknown*)pIDBI, TRUE, &pwszInitStr1), S_OK) TESTC(pwszInitStr1 != NULL) TESTC(wcslen(pwszInitStr1) > 0) //Make sure the password is the same as the one we had used to //create the DSO. if(GetModInfo()->GetStringKeywordValue(pwszInitString, L"Password", &pwszValue) && pwszValue) { TESTC_(GetModInfo()->CreateProvider(clsid, NULL, IID_IUnknown, &pIUnknown),S_OK); //Verify this property is the default on the DataSource COMPARE(GetProperty(DBPROP_AUTH_PASSWORD, DBPROPSET_DBINIT, pIUnknown, &pwszDefPassword), TRUE); if((wcscmp(pwszValue, L"")==0) || (pwszDefPassword && (wcscmp(pwszDefPassword, pwszValue)==0))) bDefault = TRUE; if(!bDefault) { TESTC(GetModInfo()->GetStringKeywordValue(pwszInitStr1, L"Password", &pwszValue1)) TESTC(wcscmp(pwszValue, pwszValue1) == 0) } } //Write the Init string into a file. TESTC_(hr = pIDI->WriteStringToStorage(L"This is a long file name for QuikTest.tst", pwszInitStr1, CREATE_ALWAYS), S_OK) //Load the init string from the file. TESTC_(hr = pIDI->LoadStringFromStorage(L"This is a long file name for QuikTest.tst", &pwszInitStr2), S_OK) //Make sure they are the same. TESTC(wcscmp(pwszInitStr1, pwszInitStr2) == 0) tTestResult = TEST_PASS; CLEANUP: remove("This is a long file name for QuikTest.tst"); FreeProperties(&cPropInfoSets, &rgPropInfoSets); FreeProperties(&cPropSets, &rgPropSets); SAFE_FREE(pwszDefPassword); SAFE_FREE(pwszProgID); SAFE_FREE(pwszInitString); SAFE_FREE(pwszInitStr1); SAFE_FREE(pwszInitStr2); SAFE_FREE(pwszValue); SAFE_FREE(pwszValue1); SAFE_RELEASE(pIDBProperties); SAFE_RELEASE(pIUnknown); SAFE_RELEASE(pIDBI); SAFE_RELEASE(pIDI); return tTestResult; } //testIDataIzGetDS //---------------------------------------------------------------------- //@mfunc Use the IGetDataSource::GetDataSource method to obtain pointers //to IDBInitialize, IDBProperties and IPersist interfaces. Verify the //obtained interfaces. Check if the obtained IDBInitialize is the same //the one we had used to initialize the Data Source Object. Use the //obtained IPersist interface to get the class ID and compare it to the //provider class ID. Use the IDBProperties to get the value of //DBPROP_INIT_PROMPT property. // TESTRESULT CQuickTest::testGetDataSource() { TESTRESULT tTestResult = TEST_FAIL; CLSID clsid; IGetDataSource* pIGetDataSource = NULL; IDBInitialize* pIDBInitialize=NULL; IDBProperties* pIDBProperties=NULL; IDBProperties* pIDBProp2=NULL; IPersist* pIPersist=NULL; VARIANT vVar; VariantInit(&vVar); //Obtain the IGetDataSource interface. if(!VerifyInterface(m_pIOpenRowset,IID_IGetDataSource, SESSION_INTERFACE,(IUnknown **)&pIGetDataSource)) { odtLog<GetDataSource(IID_IDBInitialize, (IUnknown**)&pIDBInitialize), S_OK) //The IDBInitialize obtained through this method should be the //same as m_pIDBInitialize. COMPARE(VerifyEqualInterface((IUnknown*)pIDBInitialize, (IUnknown*)m_pIDBInitialize), TRUE); //Use method to get IPersist. TESTC_(pIGetDataSource->GetDataSource(IID_IPersist, (IUnknown**)&pIPersist), S_OK) //Use the obtained IPersist interface to get class ID. //Verify that CLSID returned is identical to the Provider CLSID CHECK(pIPersist->GetClassID(&clsid), S_OK); COMPARE(clsid, GetModInfo()->GetThisTestModule()->m_ProviderClsid); //Use method to get IDBProperties. Then use the obtained IDBProperties //to get the DBPROP_INIT_PROMPT property and check its variant value. TESTC_(pIGetDataSource->GetDataSource(IID_IDBProperties, (IUnknown**)&pIDBProperties), S_OK) //Obtain the IGetDataSource interface. TESTC(VerifyInterface(m_pIDBInitialize,IID_IDBProperties, DATASOURCE_INTERFACE,(IUnknown **)&pIDBProp2)) //Verify the interface. COMPARE(VerifyEqualInterface(pIDBProperties, pIDBProp2), TRUE); //Try to get the PROMPT property using the obtained IDBProperties. if(GetProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT, pIDBProperties, &vVar)) TESTC(checkPositive_I2(&vVar)) tTestResult = TEST_PASS; CLEANUP: VariantClear(&vVar); SAFE_RELEASE(pIGetDataSource); SAFE_RELEASE(pIDBProperties); SAFE_RELEASE(pIDBProp2); SAFE_RELEASE(pIPersist); SAFE_RELEASE(pIDBInitialize); return tTestResult; } //testGetDataSource //---------------------------------------------------------------------- //@mfunc Create a table. Set two properties (BOOKMARKS, CANFETCHBACKWARDS). //Generate a rowset on the table with these properties. Then set three //properties (BOOKMARKS, CANSCROLLBACKWARDS, OWNUPDATEDELETE). Generate //a second rowset on the same table, with these three properties. Verify //the two rowsets exist and are different. Also open rowsets with each //of the mandatory interfaces of Rowset object. // TESTRESULT CQuickTest::testOpenRowset() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; IRowset* pIRowset = NULL; IRowsetInfo* pIRowsetInfo = NULL; IAccessor* pIAccessor = NULL; IColumnsInfo* pIColumnsInfo = NULL; IConvertType* pIConvertType = NULL; TESTC(m_pTable != NULL) FreeProperties(&m_cPropSets, &m_rgPropSets); //Set 2 properties. SetSettableProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets); SetSettableProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets); //Call OpenRowset #1 hr = CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)&pIRowset); CHECK(hr, S_OK); FreeProperties(&m_cPropSets, &m_rgPropSets); //Set 3 properties SetSettableProperty(DBPROP_OWNUPDATEDELETE, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets); SetSettableProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets); SetSettableProperty(DBPROP_CANSCROLLBACKWARDS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets); //Call OpenRowset #2 hr = CreateOpenRowset(m_pTable, IID_IRowsetInfo,(IUnknown**) &pIRowsetInfo); CHECK(hr, S_OK); //Verify different rowset pointers COMPARE(VerifyEqualInterface(pIRowset, pIRowsetInfo), FALSE); FreeProperties(&m_cPropSets, &m_rgPropSets); //Call OpenRowset #3 hr = CreateOpenRowset(m_pTable, IID_IAccessor,(IUnknown**) &pIAccessor); CHECK(hr, S_OK); //Call OpenRowset #4 hr = CreateOpenRowset(m_pTable, IID_IColumnsInfo,(IUnknown**) &pIColumnsInfo); CHECK(hr, S_OK); //Call OpenRowset #5 hr = CreateOpenRowset(m_pTable, IID_IConvertType,(IUnknown**) &pIConvertType); CHECK(hr, S_OK); tTestResult = TEST_PASS; CLEANUP: FreeProperties(&m_cPropSets, &m_rgPropSets); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIRowsetInfo); SAFE_RELEASE(pIAccessor); SAFE_RELEASE(pIColumnsInfo); SAFE_RELEASE(pIConvertType); return tTestResult; } //testOpenRowset //--------------------------------------------------------------------- //@mfunc Get the DBPROP_SESS_AUTOCOMMITISOLEVELS property by creating //an appropriate PROPIDSET and passing it to the GetProperties method //call. Verify the returned property and values. Then call the //GetProperties method with (0,NULL) to get all supported session //properties. Verify the returned values and properties. // TESTRESULT CQuickTest::testSessGetProp() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG cPropSets = 0; ULONG iSet=0, iProp=0 ; DBPROP* pProp = NULL; DBPROPSET* rgPropSets = NULL; ISessionProperties* pISessProp = NULL; //Obtain ISessionProperties interface. if(!VerifyInterface(m_pIOpenRowset,IID_ISessionProperties, SESSION_INTERFACE,(IUnknown **)&pISessProp)) { odtLog<GetProperties(m_cPropIDSets, m_rgPropIDSets, &cPropSets, &rgPropSets) ; //Verify that 1 DBPROPSET was returned. TESTC((cPropSets==1)&&(rgPropSets != NULL)) //Verify the guid of PropertySet. COMPARE(rgPropSets[0].guidPropertySet, DBPROPSET_SESSION); //Verify number of properties. COMPARE(rgPropSets[0].cProperties, 1); if(hr==S_OK) { //Verify status. COMPARE(rgPropSets[0].rgProperties[0].dwStatus, DBPROPSTATUS_OK); //Verify the variant. COMPARE((V_VT(&rgPropSets[0].rgProperties[0].vValue) == VT_I4), TRUE); //The value is a bitmask. So check if it is >= 0. COMPARE((V_I4(&rgPropSets[0].rgProperties[0].vValue) >= 0), TRUE); } else { odtLog<GetProperties(0, NULL, &cPropSets, &rgPropSets), S_OK) //Check return values. if(cPropSets==0 && rgPropSets==NULL) { //Issue a warning since no Property Sets were returned. odtLog<dwStatus, DBPROPSTATUS_OK); //For the property DBPROP_SESS_AUTOCOMMITISOLEVELS, verify //if the variant type is VT_I4 or VT_EMPTY. if((rgPropSets[iSet].guidPropertySet == DBPROPSET_SESSION)&& (pProp->dwPropertyID==DBPROP_SESS_AUTOCOMMITISOLEVELS)) { COMPARE((V_VT(&pProp->vValue) == VT_I4), TRUE); } //For certain variant types do some checking. COMPARE(CheckVariant(&pProp->vValue), TRUE); } } tTestResult = TEST_PASS; CLEANUP: FreeProperties(&cPropSets, &rgPropSets); FreeProperties(&m_cPropIDSets, &m_rgPropIDSets); SAFE_RELEASE(pISessProp); return tTestResult; } //testSessGetProp //--------------------------------------------------------------------- //@mfunc Set the property DBPROP_SESS_AUTOCOMMITISOLEVELS to a valid //value. After setting the property call GetProperty on it and verify. // TESTRESULT CQuickTest::testSessSetProp() { TESTRESULT tTestResult = TEST_FAIL; //Test Return Value HRESULT hr = S_OK; ULONG cPropSets = 1; DBPROP dwProp; DBPROPSET rgPropSets[1]; ISessionProperties* pISessProp = NULL; //Initialize the variant to pass as an [OUT] parameter to GetProperty. VARIANT vVar; VariantInit(&vVar); //Obtain ISessionProperties Interface. if(!VerifyInterface(m_pIOpenRowset,IID_ISessionProperties, SESSION_INTERFACE,(IUnknown **)&pISessProp)) { odtLog<SetProperties(cPropSets, rgPropSets); if(hr==S_OK) { //Check if the status is DBPROPSTATUS_OK. COMPARE(rgPropSets[0].rgProperties[0].dwStatus, DBPROPSTATUS_OK); //Call GetProperty to get the variant value of //DBPROP_SESS_AUTOCOMMITISOLEVELS. COMPARE(GetProperty(DBPROP_SESS_AUTOCOMMITISOLEVELS, DBPROPSET_SESSION, (IUnknown*)pISessProp, &vVar), TRUE); //Compare the variant value got by above call to GetProperty //and the one created (pVar) to pass in to SetProperty. COMPARE(CompareVariant(&vVar, &dwProp.vValue), TRUE); } else { odtLog<CreateCommand(NULL, IID_ICommand, (IUnknown**)&pICommand), S_OK); TESTC(pICommand != NULL) // CreateCommand with IID_ICommandText CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText, (IUnknown**)&pICommandText), S_OK); TESTC(pICommandText != NULL) // CreateCommand with IID_IColumnsInfo CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_IColumnsInfo, (IUnknown**)&pIColumnsInfo), S_OK); TESTC(pIColumnsInfo != NULL) // CreateCommand with IID_IAccessor CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_IAccessor, (IUnknown**)&pIAccessor), S_OK); TESTC(pIAccessor != NULL) // CreateCommand with IID_IConvertType CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_IConvertType, (IUnknown**)&pIConvertType), S_OK); TESTC(pIConvertType != NULL) // CreateCommand with IID_ICommandProperties CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandProperties, (IUnknown**)&pICommandProperties), S_OK); TESTC(pICommandProperties != NULL) tTestResult = TEST_PASS; CLEANUP: SAFE_RELEASE(pICommand); SAFE_RELEASE(pICommandText); SAFE_RELEASE(pIColumnsInfo); SAFE_RELEASE(pIAccessor); SAFE_RELEASE(pIConvertType); SAFE_RELEASE(pICommandProperties); return tTestResult; } //testCreateCommand //---------------------------------------------------------------------- //@mfunc Get the supported schemas. Make sure the 3 mandatory ones //(DBSCHEMA_TABLES, DBSCHEMA_COLUMNS and DBSCHEMA_PROVIDER_TYPES) are //there. // TESTRESULT CQuickTest::testGetSchemas() { TESTRESULT tTestResult = TEST_FAIL; ULONG fRequired = 0; //a bit mask to mark existing schema. ULONG ulIndex = 0; GUID * rgSchemas = NULL; ULONG cSchemas = 0; ULONG * rgRestrictionSupport = NULL; IDBSchemaRowset* pIDBSR = NULL; //Obtain IDBSchemaRowset interface if(!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset, SESSION_INTERFACE,(IUnknown**)&pIDBSR)) { odtLog<GetSchemas(&cSchemas,&rgSchemas, &rgRestrictionSupport),S_OK) TESTC((cSchemas > 2) && (rgSchemas) && (rgRestrictionSupport)) for(ulIndex=0; ulIndexGetSchemas(&cSchemas,&rgSchemas, &rgRestrictionSupport),S_OK) TESTC((cSchemas > 2) && (rgSchemas) && (rgRestrictionSupport)) //Get the restiction support. for(ulIndex=0; ulIndexGetTableName(); //Bind only 3rd column. This is the column on which we will have the //restriction. rgColsToBind[0] = 3; //If the table name restriction is supported ... if(ulRestrictCOL & 0x4) { rgRestrictions[2].vt = VT_BSTR; //Allocate memory for BSTR. Will be freed by VariantClear. SAFE_SYSALLOC(rgRestrictions[2].bstrVal, pwszTableName); } //Get the schema rowset with 1 restriction (if supported). TESTC_(hr=pIDBSR->GetRowset(NULL, DBSCHEMA_COLUMNS,4,rgRestrictions, IID_IRowset, 0, NULL, (IUnknown**) &pIRowset), S_OK) TESTC(pIRowset != NULL) TESTC(VerifyInterface(pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create Accessor with a binding using only value. //This binds the 3rd column only. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_VALUE, USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 1, rgColsToBind, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Make sure we are on the first row. TESTC_(RestartPosition(pIRowset), S_OK) //Allocate a new data buffer SAFE_ALLOC(pData, BYTE, cbRowSize) while(S_OK==(hr=GetNextRows(pIRowset, NULL, 0, 1, &cRowsObtained, &rghRows))) { //Initialize pData and call GetData for a row. memset(pData, 0, (size_t) cbRowSize); TESTC_(hr = pIRowset->GetData(*rghRows, hAccessor, pData),S_OK) CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); //If the restriction was supported, make sure it was followed. if(ulRestrictCOL & 0x4) TESTC(wcsstr((WCHAR*)((BYTE *)pData+rgBindings[0].obValue), pwszTableName) != NULL) CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings, pData), S_OK); cGotRows++; } TESTC_(hr, DB_S_ENDOFROWSET) TESTC(cGotRows > 0) tTestResult = TEST_PASS; CLEANUP: SAFE_FREE(pData); for(ulIndex=0; ulIndex<4; ulIndex++) VariantClear(&rgRestrictions[ulIndex]); CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); PROVIDER_FREE(rgSchemas); PROVIDER_FREE(rgRestrictionSupport); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIDBSR); return tTestResult; } //testColumnsSchemaRowset //---------------------------------------------------------------------- //@mfunc Get the DBSCHEMA_TABLES rowset with certain restrictions. //Verify the obtained rowset. // TESTRESULT CQuickTest::testTablesSchemaRowset() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBCOUNTITEM cRowsObtained = 0; DBCOUNTITEM cGotRows = 0; DBCOUNTITEM ulIndex = 0; HROW* rghRows = NULL; BYTE* pData = NULL; LONG_PTR rgColsToBind[2]; VARIANT rgRestrictions[4]; WCHAR* pwszTableName = NULL; ULONG ulRestrictTBL = 0; GUID * rgSchemas = NULL; ULONG cSchemas = 0; ULONG * rgRestrictionSupport = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; IAccessor* pIAccessor = NULL; IRowset* pIRowset = NULL; IDBSchemaRowset* pIDBSR = NULL; for(ulIndex=0; ulIndex<4; ulIndex++) VariantInit(&rgRestrictions[ulIndex]); //Obtain IDBSchemaRowset interface if(!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset, SESSION_INTERFACE,(IUnknown**)&pIDBSR)) { odtLog<GetSchemas(&cSchemas,&rgSchemas, &rgRestrictionSupport),S_OK) TESTC((cSchemas > 2) && (rgSchemas) && (rgRestrictionSupport)) //Get the restriction support. for(ulIndex=0; ulIndexGetTableName(); //Bind only 3rd and 4th columns. rgColsToBind[0] = 3; rgColsToBind[1] = 4; //If the table name restriction is supported ... if(ulRestrictTBL & 0x4) { rgRestrictions[2].vt = VT_BSTR; //Allocate memory for BSTR. Will be freed by VariantClear. SAFE_SYSALLOC(rgRestrictions[2].bstrVal, pwszTableName); } //If the table type restriction is supported ... if(ulRestrictTBL & 0x8) { rgRestrictions[3].vt = VT_BSTR; //Allocate memory for BSTR. Will be freed by VariantClear. SAFE_SYSALLOC(rgRestrictions[3].bstrVal, L"TABLE"); } //Get the schema rowset with 2 restrictions (if supported). TESTC_(hr=pIDBSR->GetRowset(NULL, DBSCHEMA_TABLES,4,rgRestrictions, IID_IRowset, 0, NULL, (IUnknown**) &pIRowset), S_OK) TESTC(pIRowset != NULL) TESTC(VerifyInterface(pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create Accessor with a binding using only value. //This binds the 3rd column only. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_VALUE, USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 2, rgColsToBind, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Make sure we are on the first row. TESTC_(RestartPosition(pIRowset), S_OK) //Allocate a new data buffer SAFE_ALLOC(pData, BYTE, cbRowSize) while(S_OK==(hr=GetNextRows(pIRowset, NULL, 0, 1, &cRowsObtained, &rghRows))) { //Initialize pData and call GetData for a row. memset(pData, 0, (size_t) cbRowSize); TESTC_(hr = pIRowset->GetData(*rghRows, hAccessor, pData),S_OK) CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); //If the restriction was supported, make sure it was followed. if(ulRestrictTBL & 0x4) TESTC(wcsstr((WCHAR*)((BYTE *)pData+rgBindings[0].obValue), pwszTableName) != NULL) //If the restriction was supported, make sure it was followed. if(ulRestrictTBL & 0x8) TESTC(wcsstr((WCHAR*)((BYTE *)pData+rgBindings[1].obValue), L"TABLE") != NULL) CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings, pData), S_OK); cGotRows++; } TESTC_(hr, DB_S_ENDOFROWSET) if(cGotRows == 0) { odtLog< 0, TRUE); } tTestResult = TEST_PASS; CLEANUP: SAFE_FREE(pData); for(ulIndex=0; ulIndex<4; ulIndex++) VariantClear(&rgRestrictions[ulIndex]); CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); PROVIDER_FREE(rgSchemas); PROVIDER_FREE(rgRestrictionSupport); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIDBSR); return tTestResult; } //testTablesSchemaRowset //---------------------------------------------------------------------- //@mfunc Get the DBSCHEMA_PROVIDER_TYPES rowset with certain restrictions. //Verify the obtained rowset. // TESTRESULT CQuickTest::testProvTypesSchemaRowset() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; BYTE* pData = NULL; LONG_PTR rgColsToBind[1]; VARIANT rgRestrictions[2]; ULONG ulIndex = 0; //index for no. of schemas ULONG ulRestrictPTY = 0; GUID * rgSchemas = NULL; ULONG cSchemas = 0; ULONG * rgRestrictionSupport = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; IAccessor* pIAccessor = NULL; IRowset* pIRowset = NULL; IDBSchemaRowset* pIDBSR = NULL; VariantInit(&rgRestrictions[0]); VariantInit(&rgRestrictions[1]); //Obtain IDBSchemaRowset interface if(!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset, SESSION_INTERFACE,(IUnknown**)&pIDBSR)) { odtLog<GetSchemas(&cSchemas,&rgSchemas, &rgRestrictionSupport),S_OK) TESTC((cSchemas > 2) && (rgSchemas) && (rgRestrictionSupport)) for(ulIndex=0; ulIndexGetRowset(NULL, DBSCHEMA_PROVIDER_TYPES,2, rgRestrictions, IID_IRowset, 0, NULL, (IUnknown**) &pIRowset), S_OK) TESTC(pIRowset != NULL) TESTC(VerifyInterface(pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create Accessor with a binding using only value. //Bind only the 2nd column. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_VALUE, USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 1, rgColsToBind, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Make sure we are on the first row. TESTC_(RestartPosition(pIRowset), S_OK) //Allocate a new data buffer SAFE_ALLOC(pData, BYTE, cbRowSize) while(S_OK==(hr=GetNextRows(pIRowset, NULL, 0, 1, &cRowsObtained, &rghRows))) { //Initialize pData and call GetData for a row. memset(pData, 0, (size_t) cbRowSize); TESTC_(hr = pIRowset->GetData(*rghRows, hAccessor, pData),S_OK) CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); //If the restriction was supported, make sure it was followed. if(ulRestrictPTY & 0x1) TESTC(*(USHORT*)((BYTE *)pData+rgBindings[0].obValue) == DBTYPE_BYTES) CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings, pData), S_OK); } TESTC_(hr, DB_S_ENDOFROWSET) tTestResult = TEST_PASS; CLEANUP: SAFE_FREE(pData); VariantClear(&rgRestrictions[0]); VariantClear(&rgRestrictions[1]); CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); PROVIDER_FREE(rgSchemas); PROVIDER_FREE(rgRestrictionSupport); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIDBSR); return tTestResult; } //testProvTypesSchemaRowset //---------------------------------------------------------------------- //@mfunc Add a column using ITableDefinition and verify that it was //added. // TESTRESULT CQuickTest::testAddColumn() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; BOOL fNewColumn=FALSE; DBORDINAL cOldCol = 0; DBORDINAL cNewCol = 0; DBID* pColumnID = NULL; DBID* pTableID = NULL; DBCOLUMNDESC* rgColumnDesc = NULL; DBCOLUMNDESC* rgColDesc1 = NULL; DBCOLUMNDESC* rgColDesc2 = NULL; DBCOLUMNDESC* pColumnDesc = NULL; DBORDINAL cColumnDesc = 0; DBORDINAL cColDesc1 = 0; DBORDINAL cColDesc2 = 0; CTable* pTable = NULL; CList ListNativeTemp; CList ListDataTypes; ITableDefinition* pITableDefinition = NULL; if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinition, SESSION_INTERFACE,(IUnknown**)&pITableDefinition)) { odtLog<CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES), S_OK) //build the column description array hr=pTable->BuildColumnDescs(&rgColumnDesc); TESTC(SUCCEEDED(hr)) cColumnDesc = pTable->CountColumnsOnTable(); //Set cColumnDesc-1 column descriptions. pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1); pTable->SetBuildColumnDesc(FALSE); //Create table with one less column. TESTC_(pTable->CreateTable(0, 0), S_OK) pTableID = &(pTable->GetTableIDRef()) ; hr=pTable->GetTableColumnInfo(pTableID); TESTC(SUCCEEDED(hr)) //Get column descs before calling AddColumn. TESTC(pTable->ColList2ColumnDesc(&rgColDesc1, &cColDesc1)) //The column to be added. pColumnDesc = &rgColumnDesc[cColumnDesc-1]; //Add the new column. TESTC_(hr = pITableDefinition->AddColumn(pTableID, pColumnDesc, &pColumnID), S_OK) TESTC(pColumnID != NULL) hr=pTable->GetTableColumnInfo(pTableID); TESTC(SUCCEEDED(hr)) //Get column descs after AddColumn. TESTC(pTable->ColList2ColumnDesc(&rgColDesc2, &cColDesc2)) //Number of columns should have increased by 1. TESTC(cColDesc2 == cColDesc1+1); //LOOP cColDesc1+1 times. for (cOldCol=cNewCol=0; cNewColpTypeInfo == rgColDesc2[cOldCol].pTypeInfo); TESTC(pColumnDesc->wType == rgColDesc2[cOldCol].wType); TESTC(CompareDBID(*pColumnID, rgColDesc2[cOldCol].dbcid)); //The new column has been found. fNewColumn = TRUE; } } tTestResult = TEST_PASS; CLEANUP: if(pTable) pTable->DropTable(); //rgColumnDesc gets freed above when pTable is deleted. pTable->SetNoOfColumnDesc(cColumnDesc); SAFE_DELETE(pTable); ReleaseColumnDesc(rgColDesc1, cColDesc1); ReleaseColumnDesc(rgColDesc2, cColDesc2); ReleaseDBID(pColumnID, TRUE); SAFE_RELEASE(pITableDefinition); return tTestResult; } //testAddColumn //---------------------------------------------------------------------- //@mfunc Create a table using ITableDefinition, and verify. // TESTRESULT CQuickTest::testCreateTable() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; BOOL fExists = FALSE; DBID* pNewTableID = NULL; DBCOLUMNDESC* rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; CTable* pTable = NULL; CList ListNativeTemp; CList ListDataTypes; IRowsetInfo* pIRowsetInfo = NULL; IOpenRowset* pIOpenRowset = NULL; ITableDefinition* pITableDefinition = NULL; if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinition, SESSION_INTERFACE,(IUnknown**)&pITableDefinition)) { odtLog<CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES), S_OK) //build the column description array TESTC_(hr=pTable->BuildColumnDescs(&rgColumnDesc), S_OK) cColumnDesc = pTable->CountColumnsOnTable(); //Setting the following property is not required. FreeProperties(&m_cPropSets, &m_rgPropSets); SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; //Create table with the column descriptions obtained from pTable. TESTC_(hr = pITableDefinition->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc, IID_IRowsetInfo, m_cPropSets, m_rgPropSets, &pNewTableID, (IUnknown**)&pIRowsetInfo), S_OK) //Make sure the table exists. CHECK(hr = pTable->DoesTableExist(pNewTableID, &fExists), S_OK) ; TESTC(fExists) TESTC(pIRowsetInfo != NULL) //Make sure that the IRowsetInfo obtained from CreateTable is //actually usable. hr = pIRowsetInfo->GetSpecification(IID_IOpenRowset, (IUnknown**) &pIOpenRowset) ; if(hr==S_FALSE) { odtLog<DropTable(pNewTableID); ReleaseDBID(pNewTableID, TRUE); if(hr != S_OK) { CHECK(hr, S_OK); tTestResult = TEST_FAIL; } } SAFE_DELETE(pTable); SAFE_RELEASE(pITableDefinition); return tTestResult; } //testCreateTable //---------------------------------------------------------------------- //@mfunc Drop a column from the table using ITableDefinition, and verify //that it got removed. // TESTRESULT CQuickTest::testDropColumn() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBORDINAL ulIndex = 0; BOOL bFound = FALSE; DBID* pTableID = NULL ; WCHAR* pwszNewName = NULL; DBCOLUMNDESC *rgColumnDesc = NULL; DBCOLUMNDESC *rgColDesc1 = NULL; DBORDINAL cColumnDesc = 0; DBORDINAL cColDesc1 = 0; CTable* pTable = NULL; CList ListNativeTemp; CList ListDataTypes; ITableDefinition* pITableDefinition = NULL; if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinition, SESSION_INTERFACE,(IUnknown**)&pITableDefinition)) { odtLog<CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES), S_OK) //build the column description array hr=pTable->BuildColumnDescs(&rgColumnDesc); TESTC(SUCCEEDED(hr)) cColumnDesc = pTable->CountColumnsOnTable(); //Create a table with the modified column description. pTable->SetBuildColumnDesc(FALSE); pTable->SetColumnDesc(rgColumnDesc, cColumnDesc); TESTC_(hr = pTable->CreateTable(0, 0), S_OK); pTableID = &(pTable->GetTableIDRef()) ; //Drop the column whose DBID we had modified earlier. hr = pITableDefinition->DropColumn(pTableID, &(rgColumnDesc[0].dbcid)) ; if(hr==E_NOTIMPL) { odtLog<GetTableColumnInfo(pTableID); TESTC(SUCCEEDED(hr)) TESTC(pTable->ColList2ColumnDesc(&rgColDesc1, &cColDesc1)) //Make sure the column which was dropped does not exist in the //new column desc list. for(ulIndex=0; (ulIndexDropTable(); SAFE_DELETE(pTable); //rgColumnDesc gets freed above when pTable is deleted. SAFE_RELEASE(pITableDefinition); return tTestResult; } //testDropColumn //---------------------------------------------------------------------- //@mfunc Drop a table using ITableDefinition and verify. // TESTRESULT CQuickTest::testDropTable() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; BOOL fExists = TRUE; CTable* pTable = NULL; ITableDefinition* pITableDefinition = NULL; if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinition, SESSION_INTERFACE,(IUnknown**)&pITableDefinition)) { odtLog<SetBuildColumnDesc(TRUE); //Create a table. TESTC_(hr = pTable->CreateTable((DBCOUNTITEM)0, (DBORDINAL)0, NULL), S_OK); TESTC_(hr = pITableDefinition->DropTable(&pTable->GetTableID()), S_OK); //Check if the table still exists. CHECK(hr = pTable->DoesTableExist(&pTable->GetTableID(), &fExists), S_OK) ; TESTC(!fExists) tTestResult = TEST_PASS; CLEANUP: if(pTable) pTable->DropTable(); SAFE_DELETE(pTable); SAFE_RELEASE(pITableDefinition); return tTestResult; } //testDropTable //---------------------------------------------------------------------- //@mfunc Create an Index and verify that it exists. // TESTRESULT CQuickTest::testIIndexDef() { TESTRESULT tTestResult = TEST_FAIL; TESTRESULT tTR = TEST_FAIL; HRESULT hr = S_OK; BOOL bIndexExists = FALSE; DBORDINAL cColumnDesc = 0; DBCOLUMNDESC* rgColumnDesc = NULL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; DBINDEXCOLUMNDESC* rgIndexColumnDescOut = NULL; DBID* pTableID = NULL; DBID* pIndexID = NULL; CTable* pTable = NULL; IIndexDefinition* pIID = NULL; IDBSchemaRowset* pIDSR = NULL; if(!VerifyInterface(m_pIOpenRowset,IID_IIndexDefinition, SESSION_INTERFACE,(IUnknown**)&pIID)) { odtLog<CreateTable(MIN_ROWS, 0))) //Get the column descs. TESTC_(pTable->BuildColumnDescs(&rgColumnDesc), S_OK) cColumnDesc = pTable->CountColumnsOnTable(); pTableID = &(pTable->GetTableIDRef()); //Create the index column desc. SAFE_ALLOC(rgIndexColumnDesc[0].pColumnID, DBID, 1); DuplicateDBID(rgColumnDesc[0].dbcid, rgIndexColumnDesc[0].pColumnID); rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; //Create the index. TESTC_(hr = pIID->CreateIndex(pTableID, NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK) TESTC(pIndexID != NULL) if(!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset, SESSION_INTERFACE,(IUnknown**)&pIDSR)) { odtLog<CreateIndex(pTableID, pIndexID, 1, rgIndexColumnDesc, 0, NULL, NULL), DB_E_DUPLICATEINDEXID) //Drop the index. TESTC_(hr = pIID->DropIndex(pTableID, pIndexID), S_OK) //check if the index has been dropped. if(pIDSR) { tTR = DoesIndexExist(pIDSR, pTableID, pIndexID, &bIndexExists); if(tTR==TEST_PASS) TESTC(!bIndexExists) else if(tTR==TEST_FAIL) COMPARE(tTR, TEST_PASS); } //Try to drop the index again, to verify. TESTC_(hr = pIID->DropIndex(pTableID, pIndexID), DB_E_NOINDEX) tTestResult = TEST_PASS; CLEANUP: if(pTable) pTable->DropTable(); SAFE_DELETE(pTable); ReleaseDBID(pIndexID, TRUE); ReleaseDBID(rgIndexColumnDesc[0].pColumnID, TRUE); ReleaseColumnDesc(rgColumnDesc, cColumnDesc); PROVIDER_FREE(rgIndexColumnDescOut); SAFE_RELEASE(pIDSR); SAFE_RELEASE(pIID); return tTestResult; } //testIIndexDef //---------------------------------------------------------------------- //@mfunc Test IAlterIndex::AlterIndex. // TESTRESULT CQuickTest::testAlterIndex() { TESTRESULT tTestResult = TEST_FAIL; TESTRESULT tTR = TEST_FAIL; HRESULT hr = E_FAIL; HRESULT hr1 = E_FAIL; BOOL bIndexExists = FALSE; DBORDINAL cColumnDesc = 0; DBCOLUMNDESC* rgColumnDesc = NULL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; DBID* pTableID = NULL; DBID* pIndexID = NULL; DBID dbidNewIndex; IAlterIndex* pIAI = NULL; IIndexDefinition* pIID = NULL; IDBSchemaRowset* pIDSR = NULL; IRowsetIndex* pIRI = NULL; DBORDINAL cKeyColumns = 0; DBINDEXCOLUMNDESC * rgIndexColumnDesc2 = NULL; ULONG cIndexProperties = 0; DBPROPSET * rgIndexProperties = NULL; if(!VerifyInterface(m_pIOpenRowset,IID_IAlterIndex, SESSION_INTERFACE,(IUnknown**)&pIAI)) { odtLog<BuildColumnDescs(&rgColumnDesc), S_OK) cColumnDesc = m_pTable->CountColumnsOnTable(); pTableID = &(m_pTable->GetTableIDRef()); //Create the index column desc. SAFE_ALLOC(rgIndexColumnDesc[0].pColumnID, DBID, 1); DuplicateDBID(rgColumnDesc[0].dbcid, rgIndexColumnDesc[0].pColumnID); rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; //See if IDBSchemaRowset is supported. VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset, SESSION_INTERFACE,(IUnknown**)&pIDSR); //Create the index. TESTC_(hr = pIID->CreateIndex(pTableID, NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK) TESTC(pIndexID != NULL) //Duplicate index id. DuplicateDBID(*pIndexID, &dbidNewIndex); //check if the index exists. if(pIDSR) { tTR = DoesIndexExist(pIDSR, pTableID, pIndexID, &bIndexExists); if(tTR==TEST_PASS) TESTC(bIndexExists) else if(tTR==TEST_FAIL) COMPARE(tTR, TEST_PASS); } //Modify the index name. if(dbidNewIndex.eKind == DBKIND_GUID_NAME || dbidNewIndex.eKind == DBKIND_NAME || dbidNewIndex.eKind == DBKIND_PGUID_NAME) { TESTC(_wcsset(dbidNewIndex.uName.pwszName, 'x') != NULL) } else { dbidNewIndex.uName.ulPropid++; } //Set some props. FreeProperties(&m_cPropSets, &m_rgPropSets); SetProperty(DBPROP_INDEX_FILLFACTOR, DBPROPSET_INDEX, &m_cPropSets, &m_rgPropSets, (void*)66, DBTYPE_I4, DBPROPOPTIONS_OPTIONAL) ; TEST2C_(hr1 = pIAI->AlterIndex(pTableID, pIndexID, &dbidNewIndex, m_cPropSets, m_rgPropSets), S_OK, DB_S_ERRORSOCCURRED) //check if the new index exists and old one doesn't exist. if(pIDSR) { tTR = DoesIndexExist(pIDSR, pTableID, &dbidNewIndex, &bIndexExists); if(tTR==TEST_PASS) TESTC(bIndexExists) tTR = DoesIndexExist(pIDSR, pTableID, pIndexID, &bIndexExists); if(tTR==TEST_PASS) TESTC(!bIndexExists) } //Verify using IRowsetIndex, if it is supported. TEST3C_(hr=m_pIOpenRowset->OpenRowset(NULL, pTableID, &dbidNewIndex, IID_IRowsetIndex, 0, NULL, (IUnknown**)&pIRI), S_OK, E_NOINTERFACE, DB_E_NOINDEX) if(hr == S_OK) { TESTC_(pIRI->GetIndexInfo(&cKeyColumns, &rgIndexColumnDesc2, &cIndexProperties, &rgIndexProperties), S_OK) COMPARE(cKeyColumns, 1); COMPARE(rgIndexColumnDesc2[0].eIndexColOrder, rgIndexColumnDesc[0].eIndexColOrder); COMPARE(CompareDBID(*rgIndexColumnDesc2[0].pColumnID, *rgIndexColumnDesc[0].pColumnID), TRUE); if(hr1 == S_OK) { for(ULONG i=0; iAlterIndex(pTableID, &dbidNewIndex, pIndexID, 0, NULL), S_OK, DB_E_TABLEINUSE) if(hr == DB_E_TABLEINUSE) { SAFE_RELEASE(pIRI); TESTC_(hr = pIAI->AlterIndex(pTableID, &dbidNewIndex, pIndexID, 0, NULL), S_OK) } *****/ SAFE_RELEASE(pIRI); TESTC_(hr = pIAI->AlterIndex(pTableID, &dbidNewIndex, pIndexID, 0, NULL), S_OK) tTestResult = TEST_PASS; CLEANUP: ReleaseDBID(pIndexID, TRUE); ReleaseDBID(&dbidNewIndex, FALSE); ReleaseDBID(rgIndexColumnDesc[0].pColumnID, TRUE); ReleaseColumnDesc(rgColumnDesc, cColumnDesc); FreeProperties(&m_cPropSets, &m_rgPropSets); FreeProperties(&cIndexProperties, &rgIndexProperties); SAFE_FREE(rgIndexColumnDesc2); SAFE_RELEASE(pIRI); SAFE_RELEASE(pIID); SAFE_RELEASE(pIDSR); SAFE_RELEASE(pIAI); return tTestResult; } //testAlterIndex //---------------------------------------------------------------------- //@mfunc Test IAlterTable::AlterColumn. // TESTRESULT CQuickTest::testAlterColumn() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = E_FAIL; HRESULT hr1 = E_FAIL; DBID* pTableID = NULL; DBID dbidOld; ULONG_PTR ulColFlags = 0; DBORDINAL ulCol = 0; DBORDINAL cColumns = 0; WCHAR* pStringsBuffer = NULL; DBCOLUMNINFO* rgInfo = NULL; DBCOLUMNDESCFLAGS dwColFlags = 0; DBCOLUMNDESC colDesc; IColumnsInfo* pICI = NULL; IAlterTable* pIAT = NULL; memset(&colDesc, 0, sizeof(DBCOLUMNDESC)); if(!VerifyInterface(m_pIOpenRowset,IID_IAlterTable, SESSION_INTERFACE,(IUnknown**)&pIAT)) { odtLog<GetTableIDRef()); TESTC_(m_pIOpenRowset->OpenRowset(NULL, pTableID, NULL, IID_IColumnsInfo, 0, NULL, (IUnknown**)&pICI), S_OK) //Call GetColumnInfo. TESTC_(pICI->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer),S_OK) TESTC(cColumns!=0 && rgInfo!=NULL && pStringsBuffer!=NULL) if(cColumns>1) ulCol = 1; if(ulColFlags & DBCOLUMNDESCFLAGS_PROPERTIES) dwColFlags |= DBCOLUMNDESCFLAGS_PROPERTIES; if(ulColFlags & DBCOLUMNDESCFLAGS_DBCID) dwColFlags |= DBCOLUMNDESCFLAGS_DBCID; //Duplicate column id. DuplicateDBID(rgInfo[ulCol].columnid, &colDesc.dbcid); DuplicateDBID(rgInfo[ulCol].columnid, &dbidOld); //Modify the column id. if(rgInfo[ulCol].columnid.eKind == DBKIND_GUID_NAME || rgInfo[ulCol].columnid.eKind == DBKIND_NAME || rgInfo[ulCol].columnid.eKind == DBKIND_PGUID_NAME) { TESTC(_wcsset(colDesc.dbcid.uName.pwszName, 'x') != NULL) } else { colDesc.dbcid.uName.ulPropid++; } //Set a column property. SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN, &colDesc.cPropertySets, &colDesc.rgPropertySets, (void*)VARIANT_FALSE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; //Release rowset so that the table is not in use. SAFE_RELEASE(pICI); TEST2C_(hr1 = pIAT->AlterColumn(pTableID, &rgInfo[ulCol].columnid, dwColFlags, &colDesc), S_OK, DB_S_ERRORSOCCURRED) TEST2C_(hr = pIAT->AlterColumn(pTableID, &rgInfo[ulCol].columnid, dwColFlags, &colDesc), DB_E_NOCOLUMN, DB_E_DUPLICATECOLUMNID) //Release old column info. SAFE_FREE(rgInfo); SAFE_FREE(pStringsBuffer); //Call GetColumnInfo. TESTC_(m_pIOpenRowset->OpenRowset(NULL, pTableID, NULL, IID_IColumnsInfo, 0, NULL, (IUnknown**)&pICI), S_OK) TESTC_(pICI->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer),S_OK) TESTC(cColumns!=0 && rgInfo!=NULL && pStringsBuffer!=NULL) COMPARE(CompareDBID(rgInfo[ulCol].columnid, colDesc.dbcid), TRUE); if(hr1 == S_OK) COMPARE(rgInfo[ulCol].dwFlags & DBCOLUMNFLAGS_ISNULLABLE, 0); //Remove props from the col desc, and set to old col ID. FreeProperties(&colDesc.cPropertySets, &colDesc.rgPropertySets); colDesc.cPropertySets = 0; ReleaseDBID(&colDesc.dbcid, FALSE); DuplicateDBID(dbidOld, &colDesc.dbcid); SAFE_RELEASE(pICI); TESTC_(hr = pIAT->AlterColumn(pTableID, &rgInfo[ulCol].columnid, dwColFlags, &colDesc), S_OK) tTestResult = TEST_PASS; CLEANUP: ReleaseDBID(&dbidOld, FALSE); ReleaseDBID(&colDesc.dbcid, FALSE); FreeProperties(&colDesc.cPropertySets, &colDesc.rgPropertySets); SAFE_FREE(rgInfo); SAFE_FREE(pStringsBuffer); SAFE_RELEASE(pICI); SAFE_RELEASE(pIAT); return tTestResult; } //testAlterColumn //---------------------------------------------------------------------- //@mfunc Test IAlterTable::AlterTable. // TESTRESULT CQuickTest::testAlterTable() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = E_FAIL; HRESULT hr1 = E_FAIL; DBID* pTableID = NULL; DBID dbidNew; IAlterTable* pIAT = NULL; IRowset* pIR = NULL; if(!VerifyInterface(m_pIOpenRowset,IID_IAlterTable, SESSION_INTERFACE,(IUnknown**)&pIAT)) { odtLog<GetTableIDRef()); //Duplicate index id. DuplicateDBID(*pTableID, &dbidNew); //Modify the index name. if(dbidNew.eKind == DBKIND_GUID_NAME || dbidNew.eKind == DBKIND_NAME || dbidNew.eKind == DBKIND_PGUID_NAME) { TESTC(_wcsset(dbidNew.uName.pwszName, 'x') != NULL) } else { dbidNew.uName.ulPropid++; } //Set some props. FreeProperties(&m_cPropSets, &m_rgPropSets); SetProperty(DBPROP_TBL_TEMPTABLE, DBPROPSET_TABLE, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_FALSE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; TEST3C_(hr1 = pIAT->AlterTable(pTableID, &dbidNew, m_cPropSets, m_rgPropSets), S_OK, DB_S_ERRORSOCCURRED, DB_E_DUPLICATETABLEID) //If table with that name exists, try once more with another name. if(hr1 == DB_E_DUPLICATETABLEID) { if(dbidNew.eKind == DBKIND_GUID_NAME || dbidNew.eKind == DBKIND_NAME || dbidNew.eKind == DBKIND_PGUID_NAME) { odtLog<AlterTable(pTableID, &dbidNew, m_cPropSets, m_rgPropSets), S_OK, DB_S_ERRORSOCCURRED, DB_E_DUPLICATETABLEID) if(hr1 == DB_E_DUPLICATETABLEID) { if(dbidNew.eKind == DBKIND_GUID_NAME || dbidNew.eKind == DBKIND_NAME || dbidNew.eKind == DBKIND_PGUID_NAME) odtLog<OpenRowset(NULL, pTableID, NULL, IID_IRowset, 0, NULL, (IUnknown**)&pIR), DB_E_NOTABLE) TESTC_(m_pIOpenRowset->OpenRowset(NULL, &dbidNew, NULL, IID_IRowset, 0, NULL, (IUnknown**)&pIR), S_OK) /***** //Restore old table name. TEST2C_(hr1 = pIAT->AlterTable(&dbidNew, pTableID, 0, NULL), S_OK, DB_E_TABLEINUSE) if(hr == DB_E_TABLEINUSE) { SAFE_RELEASE(pIR); TESTC_(hr1 = pIAT->AlterTable(&dbidNew, pTableID, 0, NULL), S_OK) } *****/ SAFE_RELEASE(pIR); TESTC_(hr1 = pIAT->AlterTable(&dbidNew, pTableID, 0, NULL), S_OK) tTestResult = TEST_PASS; CLEANUP: ReleaseDBID(&dbidNew, FALSE); FreeProperties(&m_cPropSets, &m_rgPropSets); SAFE_RELEASE(pIR); SAFE_RELEASE(pIAT); return tTestResult; } //testAlterTable //---------------------------------------------------------------------- //@mfunc Test the ITableDefinitionWithConstraints interface. // TESTRESULT CQuickTest::testAddAndDropConstraint() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = E_FAIL; HRESULT hr1 = E_FAIL; DBID* pTableID = NULL; DBID dbidCons; DBCONSTRAINTDESC dbConDesc; DBCOLUMNDESC* rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; CTable* pTable = NULL; CList ListNativeTemp; CList ListDataTypes; ITableDefinitionWithConstraints* pITDWC = NULL; memset(&dbConDesc, 0, sizeof(DBCONSTRAINTDESC)); if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinitionWithConstraints, SESSION_INTERFACE,(IUnknown**)&pITDWC)) { odtLog<CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES), S_OK) //build the column description array TESTC_(hr=pTable->BuildColumnDescs(&rgColumnDesc), S_OK) cColumnDesc = pTable->CountColumnsOnTable(); //Create table with the column descriptions obtained from pTable. TESTC_(hr = pITDWC->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc, IID_IRowsetInfo, 0, NULL, &pTableID, NULL), S_OK) TESTC(pTableID != NULL) //Build the DBCONSTRAINTDESC structure. dbidCons.eKind = DBKIND_NAME; dbidCons.uName.pwszName = L"QuikTest_CN1"; dbConDesc.pConstraintID = &dbidCons; dbConDesc.ConstraintType = DBCONSTRAINTTYPE_UNIQUE; dbConDesc.cColumns = 1; dbConDesc.rgColumnList = &(rgColumnDesc[0].dbcid); TESTC_(hr1 = pITDWC->AddConstraint(pTableID, &dbConDesc), S_OK) if(cColumnDesc>1) { dbConDesc.rgColumnList = &(rgColumnDesc[1].dbcid); CHECK(hr1 = pITDWC->AddConstraint(pTableID, &dbConDesc), DB_E_DUPLICATECONSTRAINTID); } TESTC_(hr1 = pITDWC->DropConstraint(pTableID, &dbidCons), S_OK) TESTC_(hr1 = pITDWC->DropConstraint(pTableID, &dbidCons), DB_E_NOCONSTRAINT) tTestResult = TEST_PASS; CLEANUP: ReleaseColumnDesc(rgColumnDesc, cColumnDesc); if(pTableID) { CHECK(hr=pITDWC->DropTable(pTableID), S_OK); ReleaseDBID(pTableID, TRUE); } SAFE_RELEASE(pITDWC); if(pTable) pTable->DropTable(); SAFE_DELETE(pTable); return tTestResult; } //testAddAndDropConstraint //---------------------------------------------------------------------- //@mfunc Test the ITableDefinitionWithConstraints interface. // TESTRESULT CQuickTest::testCreateTableWithConstraints() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = E_FAIL; DBID dbidCons; DBID dbidCons2; DBCONSTRAINTDESC rgdbConDesc[2]; BOOL fExists = FALSE; DBID* pNewTableID = NULL; DBCOLUMNDESC* rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; CTable* pTable = NULL; CList ListNativeTemp; CList ListDataTypes; ITableDefinitionWithConstraints* pITDWC = NULL; memset(rgdbConDesc, 0, 2*sizeof(DBCONSTRAINTDESC)); if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinitionWithConstraints, SESSION_INTERFACE,(IUnknown**)&pITDWC)) { odtLog<CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES), S_OK) //build the column description array TESTC_(hr=pTable->BuildColumnDescs(&rgColumnDesc), S_OK) cColumnDesc = pTable->CountColumnsOnTable(); //Setting the following property is not required. FreeProperties(&m_cPropSets, &m_rgPropSets); SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; //Build the DBCONSTRAINTDESC structure. dbidCons.eKind = DBKIND_NAME; dbidCons.uName.pwszName = L"QuikTest_CN1"; rgdbConDesc[0].pConstraintID = &dbidCons; rgdbConDesc[0].ConstraintType = DBCONSTRAINTTYPE_UNIQUE; rgdbConDesc[0].cColumns = 1; rgdbConDesc[0].rgColumnList = &(rgColumnDesc[0].dbcid); dbidCons2.eKind = DBKIND_NAME; dbidCons2.uName.pwszName = L"QuikTest_CN2"; rgdbConDesc[1].pConstraintID = &dbidCons2; rgdbConDesc[1].ConstraintType = DBCONSTRAINTTYPE_UNIQUE; rgdbConDesc[1].cColumns = 1; rgdbConDesc[1].rgColumnList = &(rgColumnDesc[1].dbcid); //Create table with the column descriptions obtained from pTable. TESTC_(hr = pITDWC->CreateTableWithConstraints(NULL, NULL, cColumnDesc, rgColumnDesc, 2, rgdbConDesc, IID_NULL, 0, NULL, &pNewTableID, NULL), S_OK) //Make sure the table exists. CHECK(hr = pTable->DoesTableExist(pNewTableID, &fExists), S_OK) ; TESTC(fExists) TESTC_(hr = pITDWC->DropConstraint(pNewTableID, &dbidCons), S_OK) TESTC_(hr = pITDWC->DropConstraint(pNewTableID, &dbidCons2), S_OK) tTestResult = TEST_PASS; CLEANUP: ReleaseColumnDesc(rgColumnDesc, cColumnDesc); if(pNewTableID) { CHECK(pITDWC->DropTable(pNewTableID), S_OK); ReleaseDBID(pNewTableID, TRUE); } SAFE_DELETE(pTable); SAFE_RELEASE(pITDWC); return tTestResult; } //testCreateTableWithConstraints //---------------------------------------------------------------------- //@mfunc Aggregate a session object and test it. // TESTRESULT CQuickTest::testAggregateSession(IDBCreateSession* pIDBCreateSession) { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; IUnknown* pIUnkInner = NULL; CAggregate Aggregate(pIDBCreateSession); //Aggregation hr = CreateNewSession(NULL, IID_IUnknown, (IUnknown**)&pIUnkInner, &Aggregate); Aggregate.SetUnkInner(pIUnkInner); //Check if aggregation is supported. if(hr==DB_E_NOAGGREGATION) { odtLog<<"Aggregation is not supported.\n"; tTestResult = TEST_SKIPPED; goto CLEANUP; } //Verify Aggregation for this session... TESTC(Aggregate.VerifyAggregationQI(hr, IID_IOpenRowset)) tTestResult = TEST_PASS; CLEANUP: SAFE_RELEASE(pIUnkInner); return tTestResult; } //testAggregateSession //---------------------------------------------------------------------- //@mfunc Obtain the IConvertType interface from the IRowset interface or //from ICommand interface. Use its CanConvert method to check for //certain conversions. // TESTRESULT CQuickTest::testIConvertType() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; HRESULT Exphr = S_OK; BOOL fRowsetCnvtOnCmd = FALSE; BOOL bDBTIME = FALSE; BOOL bNUMERIC = FALSE; BOOL bSTR = FALSE; BOOL bBYTES = FALSE; IConvertType* pICT = NULL; //COMMAND object. if(m_pICommand) { if(!VerifyInterface(m_pICommand,IID_IConvertType, COMMAND_INTERFACE,(IUnknown **)&pICT)) return TEST_FAIL; // Check to see if conversion is supported on the command if(GetProperty(DBPROP_ROWSETCONVERSIONSONCOMMAND, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize)) fRowsetCnvtOnCmd = TRUE; } //ROWSET object. else if(m_pIRowset) { if(!VerifyInterface(m_pIRowset,IID_IConvertType, ROWSET_INTERFACE,(IUnknown **)&pICT)) return TEST_FAIL; fRowsetCnvtOnCmd = TRUE; } //ROW object. else { TESTC(m_pIRow != NULL) if(!VerifyInterface(m_pIRow,IID_IConvertType, ROW_INTERFACE,(IUnknown **)&pICT)) return TEST_FAIL; fRowsetCnvtOnCmd = TRUE; } TESTC(m_pTable != NULL) GetProviderTypes(m_pTable); if(IsSupportedType(DBTYPE_DBTIME)) bDBTIME = TRUE; if(IsSupportedType(DBTYPE_NUMERIC)) bNUMERIC = TRUE; if(IsSupportedType(DBTYPE_STR)) bSTR = TRUE; if(IsSupportedType(DBTYPE_BYTES)) bBYTES = TRUE; //S_FALSE: The following conversion should not be supported. if(fRowsetCnvtOnCmd) Exphr = S_FALSE; else Exphr = DB_E_BADCONVERTFLAG; if(bNUMERIC && bDBTIME) CHECK(hr=pICT->CanConvert(DBTYPE_NUMERIC, DBTYPE_DBTIME, DBCONVERTFLAGS_COLUMN), Exphr); //S_OK: The following conversions should be supported. if(fRowsetCnvtOnCmd) Exphr = S_OK; else Exphr = DB_E_BADCONVERTFLAG; CHECK(hr=pICT->CanConvert(DBTYPE_WSTR, DBTYPE_WSTR, DBCONVERTFLAGS_COLUMN),Exphr); if(bSTR) CHECK(hr=pICT->CanConvert(DBTYPE_STR, DBTYPE_WSTR, DBCONVERTFLAGS_COLUMN),Exphr); if(bBYTES) CHECK(hr=pICT->CanConvert(DBTYPE_BYTES, DBTYPE_WSTR, DBCONVERTFLAGS_COLUMN),Exphr); tTestResult = TEST_PASS; CLEANUP: SAFE_FREE(m_rgProviderTypes); SAFE_RELEASE(pICT); return tTestResult; } //testIConvertType //---------------------------------------------------------------------- //@mfunc The IColumnsInfo interface passed in could belong to either a //rowset or a command object. Get the column info by using the //GetColumnInfo method. Verify the number of columns. Also verify the //values in the DBCOLUMNINFO structures. Obtain CCol structures by //calling CTable::GetCloInfo and use these to verify the column info //returned by the GetColumnInfo method call. // TESTRESULT CQuickTest::testGetColumnInfo(IUnknown* pIUnknown) { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; BOOL fColIDWarning = FALSE; DBORDINAL ulIndex = 0; DBORDINAL cColumns = 0; CCol rgCol; WCHAR* pStringsBuffer = NULL; DBCOLUMNINFO* rgInfo = NULL; IColumnsInfo* pIColumnsInfo = NULL; TESTC(pIUnknown != NULL) //Get IColumnsInfo. TESTC_(hr = pIUnknown->QueryInterface(IID_IColumnsInfo, (void**) &pIColumnsInfo), S_OK) //Call GetColumnInfo. TESTC_(pIColumnsInfo->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer) ,S_OK) TESTC(cColumns!=0 && rgInfo!=NULL && pStringsBuffer!=NULL) //Verify the number of columns. if(rgInfo[0].iOrdinal==0) TESTC(cColumns-1 == m_pTable->CountColumnsOnTable()) else TESTC(cColumns == m_pTable->CountColumnsOnTable()) //Verify the DBCOLUMNINFO values. for(ulIndex=0; ulIndexGetColInfo(rgInfo[ulIndex].iOrdinal, rgCol), S_OK) //Verify the column name. if((rgInfo[ulIndex].pwszName)&&(rgCol.GetColName())) TESTC(wcscmp(rgInfo[ulIndex].pwszName, rgCol.GetColName()) == 0) else TESTC((rgInfo[ulIndex].pwszName == NULL)&& (rgCol.GetColName() == NULL)) //ITypeInfo is reserved for future use. TESTC(rgInfo[ulIndex].pTypeInfo == rgCol.GetTypeInfo()) //Verify the DBTYPE. TESTC(rgInfo[ulIndex].wType == rgCol.GetProviderType()) //Compare the column IDs. if(!CompareDBID(rgInfo[ulIndex].columnid, *(rgCol.GetColID()))) { TESTC(rgInfo[ulIndex].columnid.eKind != (*(rgCol.GetColID())).eKind) fColIDWarning = TRUE; } } if(fColIDWarning) { //Issue a warning. COMPAREW(fColIDWarning, FALSE); odtLog<QueryInterface(IID_IColumnsInfo, (void**) &pIColumnsInfo), S_OK) //Get the Column DBIDs TESTC_(hr=pIColumnsInfo->GetColumnInfo(&cColumns, &rgInfo, &pStringsBuffer),S_OK) //Make array of DBIDs TESTC((cColumns>0) && (rgInfo!=NULL)) //Allocate memory for the array of DBID's SAFE_ALLOC(rgColumnIDs, DBID, sizeof(DBID) * cColumns) //Copy values into members for(ulIndex=0; ulIndexMapColumnIDs(cColumns, rgColumnIDs, rgColumns),S_OK) //Loop thru the IDs to see if they are valid. for(ulIndex = 0; ulIndexGetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) //Get number of rows. cRows = m_pTable->CountRowsOnTable(); //Donot call RestartPosition. We should be at the beginning of //the rowset. //For each row in the table, fetch the row, compare the data in the //row and release the row. for(ulIndex=0; ulIndex< (DBCOUNTITEM)cRows; ulIndex++) TESTC(GetDataAndCompare(0, 1, ulIndex+1, cRowsetCols, rgColumnsOrd, m_pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) //Call the IAccessor::GetBindings method and verify. TESTC(VerifyBindings(pIAccessor, hAccessor, cBindings, rgBindings, DBACCESSOR_ROWDATA)) tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgInfo); PROVIDER_FREE(pStringsBuffer); PROVIDER_FREE(rgStatus); PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); return tTestResult; } //testIAccessor //---------------------------------------------------------------------- //@mfunc This function is used to test IRowsetInfo::GetProperties and //ICommandProperties::GetProperties. Obtain the appropriate interface, //IRowsetInfo or ICommandProperties. Construct a DBPROPIDSET with four //properties. Call the GetProperties method with this DBPROPIDSET. Verify //the returned values and properties. Then call the GetProperties method //again with (0,NULL) to get ALL supported rowset properties. Verify the //returned values and properties. // TESTRESULT CQuickTest::testRowsetGetProp(IUnknown* pIUnknown) { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG ulSupported = 0; ULONG iSet=0, iProp=0; ULONG cPropSets = 0; DBPROP* pProp = NULL; DBPROPSET* rgPropSets = NULL; //IUnknown could either be IRowset or ICommand. IRowsetInfo* pIRowsetInfo = NULL; ICommandProperties* pICommandProperties = NULL; if(!pIUnknown) return TEST_FAIL; //Get FOUR properties FreeProperties(&m_cPropIDSets, &m_rgPropIDSets); //make DBPROPIDSET with FOUR properties in it. SetPropID(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET); SetPropID(DBPROP_OWNUPDATEDELETE, DBPROPSET_ROWSET); SetPropID(DBPROP_OWNINSERT, DBPROPSET_ROWSET); SetPropID(DBPROP_REMOVEDELETED, DBPROPSET_ROWSET); //Call GetProperties with the above made DBPROPIDSET. // IID_IRowsetInfo if((hr=pIUnknown->QueryInterface(IID_IRowsetInfo, (void **) &pIRowsetInfo))==S_OK) hr = pIRowsetInfo->GetProperties(m_cPropIDSets, m_rgPropIDSets, &cPropSets, &rgPropSets); // IID_ICommandProperties else if((hr=pIUnknown->QueryInterface(IID_ICommandProperties, (void **)&pICommandProperties))==S_OK) hr = pICommandProperties->GetProperties(m_cPropIDSets, m_rgPropIDSets, &cPropSets, &rgPropSets); //Verify that 1 DBPROPSET was returned. TESTC((cPropSets==1)&&(rgPropSets != NULL)) //Verify the guid of property set and count. COMPARE(rgPropSets[0].guidPropertySet, DBPROPSET_ROWSET); COMPARE(rgPropSets[0].cProperties, m_rgPropIDSets[0].cPropertyIDs); //Check the status of properties against the return code. if(hr == S_OK) { for(iProp=0; iPropdwStatus, DBPROPSTATUS_OK); //Verify the variant. COMPARE((V_VT(&pProp->vValue) == VT_BOOL) || (V_VT(&pProp->vValue) == VT_EMPTY), TRUE); } } else if(hr == DB_S_ERRORSOCCURRED) { for(iProp=0; iPropdwStatus != DBPROPSTATUS_OK) { //SupportedProperty() should return FALSE. COMPARE(SupportedProperty(pProp->dwPropertyID, DBPROPSET_ROWSET), FALSE); //CANHOLDROWS cannot be among the not supported props. COMPARE(pProp->dwPropertyID != DBPROP_CANHOLDROWS, TRUE); } else ulSupported++; } //At least one prop has to be supported for this return code. //Also, all props cannot be supported for this return code. COMPARE(ulSupported >0, TRUE); COMPARE(ulSupported <4, TRUE); } else { //At least CANHOLDROWS has to be supported. TESTC_(hr, S_OK) } FreeProperties(&cPropSets, &rgPropSets); //Get ALL properties. if(pIRowsetInfo != NULL) hr = pIRowsetInfo->GetProperties(0, NULL, &cPropSets, &rgPropSets); // IID_ICommandProperties else { TESTC(pICommandProperties != NULL) hr = pICommandProperties->GetProperties(0, NULL, &cPropSets, &rgPropSets); } //At least CANHOLDROWS should be supported. TESTC_(hr, S_OK) //Check return values. TESTC((cPropSets!=0) && (rgPropSets!=NULL)) //Loop through the property sets. for(iSet=0; iSetdwStatus, DBPROPSTATUS_OK); //For the properties DBPROP_CANHOLDROWS, DBPROP_OWNINSERT, //DBPROP_OWNUPDATEDELETE and DBPROP_REMOVEDELETED verify //if the variant type is VT_BOOL or VT_EMPTY. if((rgPropSets[iSet].guidPropertySet == DBPROPSET_ROWSET)&& ((pProp->dwPropertyID==DBPROP_CANHOLDROWS) || (pProp->dwPropertyID==DBPROP_OWNUPDATEDELETE) || (pProp->dwPropertyID==DBPROP_OWNINSERT) || (pProp->dwPropertyID==DBPROP_REMOVEDELETED))) { if(V_VT(&pProp->vValue) == VT_BOOL) { COMPARE(CheckVariant(&pProp->vValue), TRUE); } else { COMPARE(V_VT(&pProp->vValue), VT_EMPTY); } } //For certain variant types do some checking. COMPARE(CheckVariant(&pProp->vValue), TRUE); } } tTestResult = TEST_PASS; CLEANUP: FreeProperties(&cPropSets, &rgPropSets); FreeProperties(&m_cPropIDSets, &m_rgPropIDSets); SAFE_RELEASE(pIRowsetInfo); SAFE_RELEASE(pICommandProperties); return tTestResult; } //testRowsetGetProp //---------------------------------------------------------------------- //@mfunc Obtain the IRowsetInfo interface. Call the method //GetReferencedRowset. Pass it the ordinal of the bookmark column which //is used to obtain the rowset corresponding to these //bookmarks. Verify that the obtained IRowset interface is the same as //the one we got on generating this rowset. // TESTRESULT CQuickTest::testIRowsetInfoGetRefRowset() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; BOOL bBookmarksSupp = FALSE; IRowset* pIRowset = NULL; IRowsetInfo* pIRI = NULL; //Obtain the IRowsetInfo interface. if(!VerifyInterface(m_pIRowset,IID_IRowsetInfo, ROWSET_INTERFACE,(IUnknown**)&pIRI)) return TEST_FAIL; if(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset)) bBookmarksSupp = TRUE; //Use the method to obtain the IRowset interface and verify it is //the same as the one we got on creating the rowset. hr = pIRI->GetReferencedRowset(0, IID_IRowset, (IUnknown**) &pIRowset) ; if(bBookmarksSupp) { TESTC_(hr, S_OK) TESTC(VerifyEqualInterface((IUnknown*)pIRowset,(IUnknown*)m_pIRowset)) } else { odtLog<<"Bookmarks are not supported.\n"; TESTC_(hr, DB_E_BADORDINAL) tTestResult = TEST_SKIPPED; goto CLEANUP ; } tTestResult = TEST_PASS; CLEANUP: SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIRI); return tTestResult; } //testIRowsetInfoGetRefRowset //---------------------------------------------------------------------- //@mfunc Obtain the IRowsetInfo interface. Use its GetSpecification //method to obtain the IOpenRowset interface. Verify that this is the //same interface which we had obtained on creating this DB Session. Use //the GetSpecification method again to obtain the IGetDataSource //interface. Verify this interface by using it to obtain the //IDBInitialize interface (using IGetDataSource::GetDataSource) and //verifying that it is the same as the IDBInitialize interface which //was used to initialize the Data Source Object. // TESTRESULT CQuickTest::testIRowsetInfoGetSpec() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; IOpenRowset* pIOR = NULL; IGetDataSource* pIGDS = NULL; IDBInitialize* pIDBI = NULL; IRowsetInfo* pIRI = NULL; //Obtain IRowsetInfo interface. if(!VerifyInterface(m_pIRowset,IID_IRowsetInfo, ROWSET_INTERFACE,(IUnknown**)&pIRI)) return TEST_FAIL; //Use the method to obtain the IOpenRowset Interface. TEST2C_(hr = pIRI->GetSpecification(IID_IOpenRowset, (IUnknown**)&pIOR), S_OK, S_FALSE) //The method can return S_FALSE if the provider does not have an //object that created the rowset. if(hr == S_OK) { COMPARE(VerifyEqualInterface((IUnknown*)pIOR, (IUnknown*)m_pIOpenRowset), TRUE); } else { odtLog<GetSpecification(IID_IGetDataSource, (IUnknown**)&pIGDS), S_OK, S_FALSE) if(hr == S_OK) { TESTC_(pIGDS->GetDataSource(IID_IDBInitialize, (IUnknown**)&pIDBI), S_OK) COMPARE(VerifyEqualInterface((IUnknown*)pIDBI, (IUnknown*)m_pIDBInitialize), TRUE); } else { odtLog<CreateCommand(NULL, IID_ICommand,(IUnknown **)&pICommand),S_OK) } else { odtLog<ExecuteCommand(SELECT_ALLFROMTBL, IID_IRowsetInfo, NULL, NULL, NULL, NULL, EXECUTE_IFNOERROR, 0, NULL, NULL, (IUnknown**)&pIRI, &pICommand), S_OK); TESTC(pIRI != NULL) //Use the method to obtain the IColumnsInfo Interface. TEST2C_(hr = pIRI->GetSpecification(IID_IColumnsInfo, (IUnknown**)&pIColumnsInfo), S_OK, S_FALSE) //The method can return S_FALSE if the provider does not have an //object that created the rowset. if(hr == S_OK) { TESTC(VerifyEqualInterface(pICommand, pIColumnsInfo)) } else { odtLog<GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) //Count number of rows on the table cRows = m_pTable->CountRowsOnTable(); TESTC(cRows >= MIN_ROWS) //Make sure we are on the first row. TESTC_(RestartPosition(pIRowset), S_OK) //Skip the 1st row and fetch the 2nd row. TESTC(GetDataAndCompare(1, 1, 2, cRowsetCols, rgColumnsOrd, pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) //Skip 2 more rows and fetch the 5th row. TESTC(GetDataAndCompare(2, 1, 5, cRowsetCols, rgColumnsOrd, pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) //Restart position. TESTC_(RestartPosition(pIRowset), S_OK) //Skip 3 rows and fetch the 4th row. TESTC(GetDataAndCompare(3, 1, 4, cRowsetCols, rgColumnsOrd, pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) //Skip 0 and fetch the 5th row. TESTC(GetDataAndCompare(0, 1, 5, cRowsetCols, rgColumnsOrd, pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) //Restart position. TESTC_(RestartPosition(pIRowset), S_OK) //Try to open more than 2 rows at a time if the MAXOPENROWS property //permits this. if(m_ulMaxOpenRows>1 || m_ulMaxOpenRows==0) { TESTC_(hr = GetNextRows(pIRowset, NULL, 0, 2, &cRowsObtained, (HROW**)&rghRows), S_OK) CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); } tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowset); return tTestResult; } //testIRowset2 //---------------------------------------------------------------------- //@mfunc Set the properties CANHOLDROWS and CANSCROLLBACKWARDS. Generate //a rowset on the table using these properties. Get the accessor and //bindings. Call method RestartPosition. Skip 4 rows in the forward //direction and fetch the 5th row (method GetNextRows). Get its data //(method GetData) and compare. Scroll backwards 2 rows and fetch the //3rd row. Compare its data. Scroll backwards again 1 row to fetch the //2nd row. Compare its data. Finally release all the rows we obtained //above. // TESTRESULT CQuickTest::testIRowset3() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBCOUNTITEM cRows = 0; DBORDINAL cColumns = 0; DB_LORDINAL* rgColumnsOrd = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; //The properties DBPROP_CANHOLDROWS and DBPROP_CANSCROLLBACKWARDS //have been set. TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create Accessor with a binding using length, //status and value. This accessor binds the Index //column also. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Get list of ordinals. TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cColumns, &rgColumnsOrd, NULL, NULL, NULL, NULL)) //Count number of rows on the table cRows = m_pTable->CountRowsOnTable(); TESTC(cRows >= MIN_ROWS); //Make sure we are on the first row. TESTC_(RestartPosition(m_pIRowset), S_OK) //Skip 4 rows and fetch the 5th row. Compare its data. TESTC(GetDataAndCompare(4, 1, 5, cColumns, rgColumnsOrd, m_pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) //Scroll backwards 2 rows and fetch the 3rd row. Compare its data. TESTC(GetDataAndCompare(-3, 1, 3, cColumns, rgColumnsOrd, m_pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) //Scroll backwards 1 row and fetch the 2rd row. Compare its data. TESTC(GetDataAndCompare(-2, 1, 2, cColumns, rgColumnsOrd, m_pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); return tTestResult; } //testIRowset3 //---------------------------------------------------------------------- //@mfunc Get bookmarks for rows 1, 2 and 4. Use IRowsetLocate::Compare //to compare them. // TESTRESULT CQuickTest::testIRowsetLocateCompare() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBBKMARK rgcbBookmarks[3]; BYTE *rgpBookmarks[3]={NULL,NULL,NULL}; DBBOOKMARK dbBkm = DBBMK_FIRST; BYTE* pBkm = (BYTE*) &dbBkm; DBBOOKMARK dbBkm2 = DBBMK_LAST; BYTE* pBkm2 = (BYTE*) &dbBkm; DBCOMPARE dwComparison1 = DBCOMPARE_NOTCOMPARABLE; DBCOMPARE dwComparison2 = DBCOMPARE_NOTCOMPARABLE; DBCOMPARE dwComparison3 = DBCOMPARE_NOTCOMPARABLE; DBCOMPARE dwComparison4 = DBCOMPARE_NOTCOMPARABLE; DBCOMPARE dwComparison5 = DBCOMPARE_NOTCOMPARABLE; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; IRowsetLocate* pIRowsetLocate = NULL; TESTC(VerifyInterface(m_pIRowset,IID_IRowsetLocate, ROWSET_INTERFACE,(IUnknown**)&pIRowsetLocate)) TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create an accessor. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG, NULL),S_OK) //get the bookmark for the 1st row TESTC(GetBookmark(1,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0])) //get the bookmark for the 2nd row TESTC(GetBookmark(2,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[1],&rgpBookmarks[1])) //get the bookmark for the 4th row TESTC(GetBookmark(4,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[2],&rgpBookmarks[2])) //Compare rows 2 and 4. TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[1],rgpBookmarks[1], rgcbBookmarks[2],rgpBookmarks[2],&dwComparison1),S_OK) //Compare rows 4 and 1. TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[2],rgpBookmarks[2], rgcbBookmarks[0],rgpBookmarks[0],&dwComparison2),S_OK) //Compare rows 2 and DBBMK_FIRST. TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[1],rgpBookmarks[1], STD_BOOKMARKLENGTH,pBkm,&dwComparison3),S_OK) //Compare rows 4 and 4. TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[2],rgpBookmarks[2], rgcbBookmarks[2],rgpBookmarks[2],&dwComparison4),S_OK) //Compare rows 2 and DBBMK_LAST. TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[1],rgpBookmarks[1], STD_BOOKMARKLENGTH,pBkm2,&dwComparison5),S_OK) //check the comparisons. //If ordered-bookmarks are supported. if(GetProperty(DBPROP_ORDEREDBOOKMARKS, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset)) { COMPARE(dwComparison1, DBCOMPARE_LT); COMPARE(dwComparison2, DBCOMPARE_GT); COMPARE(dwComparison3, DBCOMPARE_NE); COMPARE(dwComparison4, DBCOMPARE_EQ); COMPARE(dwComparison5, DBCOMPARE_NE); } else { COMPARE(dwComparison1, DBCOMPARE_NE); COMPARE(dwComparison2, DBCOMPARE_NE); COMPARE(dwComparison3, DBCOMPARE_NE); COMPARE(dwComparison4, DBCOMPARE_EQ); COMPARE(dwComparison5, DBCOMPARE_NE); } tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgpBookmarks[0]); PROVIDER_FREE(rgpBookmarks[1]); PROVIDER_FREE(rgpBookmarks[2]); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetLocate); return tTestResult; } //testIRowsetLocateCompare //---------------------------------------------------------------------- //@mfunc Use IRowsetLocate::GetRowsAt to fetch rows with respect to a //row whose bookmark is provided. // TESTRESULT CQuickTest::testIRowsetLocateGetRowsAt() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG ulIndex = 0; //small no. DBBKMARK rgcbBookmarks[1]; BYTE *rgpBookmarks[1] = {NULL}; DBBOOKMARK dbBkm = DBBMK_FIRST; BYTE* pBkm = (BYTE*) &dbBkm; BYTE* pData = NULL; HROW* rghRows = NULL; DB_LORDINAL* rgColumnsOrd = NULL; DBORDINAL cColumns = 0; DBCOUNTITEM cRowsObtained = 0; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; IRowsetLocate* pIRowsetLocate = NULL; TESTC(VerifyInterface(m_pIRowset,IID_IRowsetLocate, ROWSET_INTERFACE,(IUnknown**)&pIRowsetLocate)) TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create an accessor. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG, NULL),S_OK) TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cColumns, &rgColumnsOrd, NULL,NULL,NULL,NULL)) //get the bookmark for the 2nd row TESTC(GetBookmark(2,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0])) //Fetch 3rd and 4th rows. TESTC_(hr=pIRowsetLocate->GetRowsAt(NULL, NULL, rgcbBookmarks[0], rgpBookmarks[0], 1, 2, &cRowsObtained, &rghRows), S_OK) SAFE_ALLOC(pData, BYTE, cbRowSize); TESTC(cRowsObtained==2 && rghRows) for(ulIndex=0; ulIndexGetData(rghRows[ulIndex], hAccessor, pData), S_OK) TESTC(CompareData(cColumns, rgColumnsOrd, 3+ulIndex, pData, cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY)) ReleaseInputBindingsMemory(cBindings, rgBindings, pData); } CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK); //Fetch the 3rd and 4th rows using standard bookmarks. TESTC_(hr=pIRowsetLocate->GetRowsAt(NULL, NULL, STD_BOOKMARKLENGTH, pBkm, 2, 2, &cRowsObtained, &rghRows), S_OK) TESTC(cRowsObtained==2 && rghRows) for(ulIndex=0; ulIndexGetData(rghRows[ulIndex], hAccessor, pData), S_OK) TESTC(CompareData(cColumns, rgColumnsOrd, 3+ulIndex, pData, cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY)) ReleaseInputBindingsMemory(cBindings, rgBindings, pData); } CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK); //SCROLL_BACKWARDS //Fetch 1st, 2nd, and 3rd rows using SCROLL_BACKWARDS. hr = pIRowsetLocate->GetRowsAt(NULL, NULL, rgcbBookmarks[0], rgpBookmarks[0], -1, 3, &cRowsObtained, &rghRows) ; if(GetProperty(DBPROP_CANSCROLLBACKWARDS, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset)) { TESTC_(hr, S_OK) TESTC(cRowsObtained==3 && rghRows) } else { CHECK(hr, DB_E_CANTSCROLLBACKWARDS); tTestResult = TEST_PASS; goto CLEANUP; } for(ulIndex=0; ulIndexGetData(rghRows[ulIndex], hAccessor, pData), S_OK) TESTC(CompareData(cColumns, rgColumnsOrd, 1+ulIndex, pData, cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY)) ReleaseInputBindingsMemory(cBindings, rgBindings, pData); } tTestResult = TEST_PASS; CLEANUP: SAFE_FREE(pData); CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK); PROVIDER_FREE(rgpBookmarks[0]); PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetLocate); return tTestResult; } //testIRowsetLocateGetRowsAt //---------------------------------------------------------------------- //@mfunc Get bookmarks to some rows and pass this in to IRowsetLocate:: //GetRowsByBookmark. Verify the returned rows. // TESTRESULT CQuickTest::testIRowsetLocateGetRowsByBkm() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG ulIndex = 0; // max 3 DBCOUNTITEM cGotRows = 0; DBCOUNTITEM iRowNum[3] = {2,4,5}; //Row numbers of rows to get. DB_LORDINAL* rgColumnsOrd = NULL; DBORDINAL cColumns = 0; BYTE* pData = NULL; DBBKMARK rgcbBookmarks[3]; BYTE *rgpBookmarks[3]={NULL,NULL,NULL}; DBROWSTATUS rgRowStatus[3]; //Not required to initialize. HROW rghRows[3] ; //Not required to initialize. DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; IRowsetLocate* pIRowsetLocate = NULL; TESTC(VerifyInterface(m_pIRowset,IID_IRowsetLocate, ROWSET_INTERFACE,(IUnknown**)&pIRowsetLocate)) TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create an accessor. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG, NULL),S_OK) TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cColumns, &rgColumnsOrd, NULL,NULL,NULL,NULL)) //get the bookmark for the 2nd row TESTC(GetBookmark(2,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0])) //get the bookmark for the 4th row TESTC(GetBookmark(4,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[1],&rgpBookmarks[1])) //get the bookmark for the 5th row TESTC(GetBookmark(5,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[2],&rgpBookmarks[2])) TESTC_(hr=pIRowsetLocate->GetRowsByBookmark(NULL, 3, rgcbBookmarks, (const BYTE**)rgpBookmarks, rghRows, rgRowStatus), S_OK) for(ulIndex=0; ulIndex<3; ulIndex++) { TESTC(rghRows[ulIndex] != DB_NULL_HROW) cGotRows++; COMPARE(rgRowStatus[ulIndex] , DBROWSTATUS_S_OK); } SAFE_ALLOC(pData, BYTE, cbRowSize); for(ulIndex=0; ulIndex<3; ulIndex++) { memset(pData, 0, (size_t) cbRowSize); TESTC_(hr=m_pIRowset->GetData(rghRows[ulIndex], hAccessor, pData), S_OK) COMPARE(CompareData(cColumns, rgColumnsOrd, iRowNum[ulIndex], pData, cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY), TRUE); ReleaseInputBindingsMemory(cBindings, rgBindings, pData); } tTestResult = TEST_PASS; CLEANUP: SAFE_FREE(pData); CHECK(m_pIRowset->ReleaseRows(3, rghRows, NULL,NULL,NULL), S_OK); PROVIDER_FREE(rgColumnsOrd); PROVIDER_FREE(rgpBookmarks[0]); PROVIDER_FREE(rgpBookmarks[1]); PROVIDER_FREE(rgpBookmarks[2]); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetLocate); return tTestResult; } //testIRowsetLocateGetRowsByBkm //---------------------------------------------------------------------- //@mfunc Get hash values for certain bookmarks. // TESTRESULT CQuickTest::testIRowsetLocateHash() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG ulIndex = 0; //max 3 DBBKMARK rgcbBookmarks[3]; BYTE *rgpBookmarks[3]={NULL,NULL,NULL}; DBHASHVALUE rgHashedValues[3]; //Not required to initialize. DBROWSTATUS rgBookmarkStatus[3]; //Not required to initialize. DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; IRowsetLocate* pIRowsetLocate = NULL; TESTC(VerifyInterface(m_pIRowset,IID_IRowsetLocate, ROWSET_INTERFACE,(IUnknown**)&pIRowsetLocate)) TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create an accessor. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG, NULL),S_OK) //get the bookmark for the 1st row TESTC(GetBookmark(1,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0])) //get the bookmark for 1st row again TESTC(GetBookmark(1,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[1],&rgpBookmarks[1])) //get the bookmark for the 4th row TESTC(GetBookmark(4,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[2],&rgpBookmarks[2])) //Hash returns different values TESTC_(hr = pIRowsetLocate->Hash(NULL,3,rgcbBookmarks, (const BYTE **)rgpBookmarks, rgHashedValues,rgBookmarkStatus), S_OK) for(ulIndex=0; ulIndex<3; ulIndex++) { COMPARE(rgBookmarkStatus[ulIndex] , DBROWSTATUS_S_OK); } //The first 2 hash values are for the first row, hence they //should be equal. The third one should be different. COMPARE(rgHashedValues[0] == rgHashedValues[1], TRUE); COMPARE(rgHashedValues[1] != rgHashedValues[2], TRUE); COMPARE(rgHashedValues[0] != rgHashedValues[2], TRUE); tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgpBookmarks[0]); PROVIDER_FREE(rgpBookmarks[1]); PROVIDER_FREE(rgpBookmarks[2]); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetLocate); return tTestResult; } //testIRowsetLocateHash //---------------------------------------------------------------------- //@mfunc Make data corresponding to a certain row and column (choosing a //fixed length column). Use this as the search criterion for FindNextRow. //Verify the obtained rows. // TESTRESULT CQuickTest::testFindNextRow() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBORDINAL ulIndex = 0; DBORDINAL cRowsetCols = 0; DB_LORDINAL* rgColumnsOrd = NULL; DBORDINAL cColumns = 0; DBCOUNTITEM ulRowNum = 0; DB_LORDINAL ulColNum = 0; DBLENGTH cbDataLength = 0; DBCOLUMNINFO* rgInfo = NULL; WCHAR* pStrBuf = NULL; WCHAR wszData[2000]; BYTE* pMakeData = NULL; void* pvData = NULL; BYTE* pFindValue = NULL; BYTE* pData = NULL; DBTYPE wColType = DBTYPE_EMPTY; DBTYPE wVariantType = DBTYPE_EMPTY; DBBKMARK rgcbBookmarks[1]; BYTE *rgpBookmarks[1]={NULL}; HROW* rghRows = NULL ; DBCOUNTITEM cRowsObtained = 0; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; IColumnsInfo* pIColumnsInfo = NULL; IRowsetFind* pIRowsetFind = NULL; TESTC(VerifyInterface(m_pIRowset,IID_IRowsetFind, ROWSET_INTERFACE,(IUnknown**)&pIRowsetFind)) TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create an accessor. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG, NULL),S_OK) //Bookmark will be got for the following row num. ulRowNum = 2; //get the bookmark for the 'ulRowNum' row TESTC(GetBookmark(ulRowNum,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0])) //Release hAccessor and free bindings. But don't release IAccessor. FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings, FALSE); TESTC(VerifyInterface(m_pIRowset,IID_IColumnsInfo, ROWSET_INTERFACE,(IUnknown**)&pIColumnsInfo)) TESTC_(hr = pIColumnsInfo->GetColumnInfo(&cColumns, &rgInfo, &pStrBuf), S_OK) //Get a fixed-length column whose data we will use for the FindRow. for(ulIndex=1; ulIndexMakeData(wszData, ulRowNum, ulColNum, PRIMARY, wColType, TRUE, &wVariantType), S_OK) //If it is a variant, then use correct variant type. pMakeData = (BYTE *)WSTR2DBTYPE(wszData, ( wColType == DBTYPE_VARIANT ? wVariantType : wColType) ,NULL ); cbDataLength = GetDBTypeSize(wColType) ; SAFE_ALLOC(pFindValue, BYTE, cbDataLength+offsetof(DATA, bValue)) //If the find value is to be a variant then convert the data to //a variant. if ( wColType == DBTYPE_VARIANT ) pvData = DBTYPE2VARIANT(pMakeData, wVariantType); else pvData = pMakeData; //Create the binding for the find value. memcpy(pFindValue+offsetof(DATA, bValue), pvData, (size_t) cbDataLength); *(DBSTATUS *)(pFindValue+offsetof(DATA, sStatus)) = DBSTATUS_S_OK; *(DBLENGTH *)(pFindValue+offsetof(DATA, ulLength)) = cbDataLength; //Create an accessor and binding for one column (ulColNum). TESTC_(hr = GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA, &hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH, USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 1, &ulColNum, NULL, NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG ), S_OK) //Call the method (FindNextRow) to be tested. hr = pIRowsetFind->FindNextRow(NULL, hAccessor, pFindValue, DBCOMPAREOPS_EQ, rgcbBookmarks[0], rgpBookmarks[0], 0, 2, &cRowsObtained, &rghRows) ; //Make sure we got back 2 rows. TESTC_(hr, S_OK) TESTC(cRowsObtained == 2) SAFE_ALLOC(pData, BYTE, cbRowSize); memset(pData, 0, (size_t) cbRowSize); //Get data for the first of the 2 rows. The data in this should //match our search data. TESTC_(hr = m_pIRowset->GetData(rghRows[0], hAccessor, pData), S_OK) TESTC(CompareBuffer((void*)pData, (void*)pFindValue, 1, rgBindings, m_pIMalloc, FALSE, FALSE, COMPARE_ONLY)) ReleaseInputBindingsMemory(cBindings, rgBindings, pData); memset(pData, 0, (size_t) cbRowSize); //Get the data for the second of the 2 rows. This should be the //row which comes right after the row which matched the search //data. TESTC_(hr = m_pIRowset->GetData(rghRows[1], hAccessor, pData), S_OK) //Get list of ordinals. TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) TESTC(CompareData(cRowsetCols,rgColumnsOrd,ulRowNum+1,pData,1, rgBindings, m_pTable, m_pIMalloc, PRIMARY)) tTestResult = TEST_PASS; CLEANUP: ReleaseInputBindingsMemory(cBindings, rgBindings, pData); SAFE_FREE(pData); CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK); PROVIDER_FREE(rgpBookmarks[0]); PROVIDER_FREE(pStrBuf); PROVIDER_FREE(pvData); PROVIDER_FREE(rgInfo); PROVIDER_FREE(rgColumnsOrd); SAFE_FREE(pFindValue); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIColumnsInfo); SAFE_RELEASE(pIRowsetFind); return tTestResult; } //testFindNextRow //---------------------------------------------------------------------- //@mfunc Get the bookmarks for some rows and obtain their approximate //position by calling the method GetApproximatePosition. Verify that //the positions returned have reasonable approximations. // TESTRESULT CQuickTest::testGetApproxPos() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBBKMARK rgcbBookmarks[3]; BYTE *rgpBookmarks[3]={NULL,NULL,NULL}; DBCOUNTITEM cRowsOnTable = 0; DBCOUNTITEM cRows = 0; DBCOUNTITEM ulPosition = 0; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; IRowsetScroll* pIRS = NULL; TESTC(VerifyInterface(m_pIRowset,IID_IRowsetScroll, ROWSET_INTERFACE,(IUnknown**)&pIRS)) TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create an accessor. TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG, NULL),S_OK) //get the bookmark for the 1st row TESTC(GetBookmark(1,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0])) //get the bookmark for the 3rd row TESTC(GetBookmark(3,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[1],&rgpBookmarks[1])) //get the bookmark for the 5th row TESTC(GetBookmark(5,cbRowSize,hAccessor,cBindings, rgBindings, (IUnknown*)m_pIRowset, &rgcbBookmarks[2],&rgpBookmarks[2])) cRowsOnTable = m_pTable->CountRowsOnTable(); //Bookmark for row 1. TESTC_(hr = pIRS->GetApproximatePosition(NULL, rgcbBookmarks[0], rgpBookmarks[0], &ulPosition, &cRows), S_OK) TESTC(cRows >= ulPosition) odtLog<GetApproximatePosition(NULL, rgcbBookmarks[1], rgpBookmarks[1], &ulPosition, &cRows), S_OK) TESTC(cRows >= ulPosition) odtLog<GetApproximatePosition(NULL, rgcbBookmarks[2], rgpBookmarks[2], &ulPosition, &cRows), S_OK) TESTC(cRows >= ulPosition) odtLog<CountRowsOnTable(); //Pass in 0 for numerator and cRowsOnTable for denominator. This //is guaranteed to fetch the first 3 rows. TESTC_(hr = pIRS->GetRowsAtRatio(NULL, NULL, 0, cRowsOnTable, 3, &cRowsObtained, &rghRows), S_OK) TESTC(cRowsObtained == 3) TESTC(rghRows != NULL) //Position cursor to beginning of rowset. TESTC_(RestartPosition(m_pIRowset), S_OK) //Fetch the first 3 rows using GetNextRows. TESTC_(hr = GetNextRows(m_pIRowset, NULL, 0, 3, &cRowsObtained2, &rghRows2), S_OK) //Verify that the rows returned by GetRowsAtRatio are the same as //that fetched by GetNextRows. for(ulIndex=0; ulIndexIsSameRow(rghRows[ulIndex], rghRows2[ulIndex]), S_OK) tTestResult = TEST_PASS; CLEANUP: CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK); CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained2, &rghRows2), S_OK); SAFE_RELEASE(pIRI); SAFE_RELEASE(pIRS); return tTestResult; } //testGetRowsAtRatio //---------------------------------------------------------------------- //@mfunc Initialize IRowPosition with m_pIRowset. Then call the various //methods of IRowPosition and verify their functionality. // TESTRESULT CQuickTest::testIRowPosition() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; HROW* rghRows = NULL; HROW hRows2 = DB_NULL_HROW; DBCOUNTITEM cRowsObtained = 0; VARIANT_BOOL bValue = VARIANT_FALSE; IRowsetInfo* pIRI = NULL; IRowPosition* pIRowPosition = NULL; hr = CoCreateInstance(CLSID_OLEDB_ROWPOSITIONLIBRARY, NULL, CLSCTX_INPROC_SERVER, IID_IRowPosition, (LPVOID *)&pIRowPosition); if(hr != S_OK) { odtLog<Initialize((IUnknown*)m_pIRowset), S_OK) //Call GetRowset to obtain IRowsetInfo. TESTC_(hr = pIRowPosition->GetRowset(IID_IRowsetInfo, (IUnknown**) &pIRI), S_OK) TESTC(pIRI != NULL) //Use the obtained IRowsetInfo interface. TESTC(GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, (IUnknown*) pIRI, &bValue)) //Clear any existing row position. TESTC_(hr = pIRowPosition->ClearRowPosition(), S_OK) //Position cursor to beginning of rowset. TESTC_(RestartPosition(m_pIRowset), S_OK) //Get the handle to the 2nd row. TESTC_(hr = GetNextRows(m_pIRowset, NULL, 1, 1, &cRowsObtained, &rghRows), S_OK) //Set the row position to the 2nd row. TESTC_(hr = pIRowPosition->SetRowPosition(NULL, rghRows[0], DBPOSITION_OK), S_OK) TESTC_(hr = m_pIRowset->ReleaseRows(1,rghRows, NULL, NULL, NULL),S_OK); //Get the current row position. TESTC_(hr = pIRowPosition->GetRowPosition(NULL, &hRows2, NULL), S_OK) //Make sure it is same as the one we had set. TESTC(rghRows[0] == hRows2) TESTC_(hr = m_pIRowset->ReleaseRows(1,rghRows, NULL, NULL, NULL),S_OK); tTestResult = TEST_PASS; CLEANUP: CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK); SAFE_RELEASE(pIRI); SAFE_RELEASE(pIRowPosition); return tTestResult; } //testIRowPosition //---------------------------------------------------------------------- //@mfunc Aggregate the rowset and test it. // TESTRESULT CQuickTest::testAggregateRowset() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr; IUnknown* pIUnkInner = NULL; CAggregate Aggregate(m_pIOpenRowset); TESTC(m_pTable && m_pIOpenRowset) //Aggregation hr = CreateOpenRowset(m_pTable, IID_IUnknown, (IUnknown**)&pIUnkInner, &Aggregate); Aggregate.SetUnkInner(pIUnkInner); //Check if aggregation is supported. if(hr==DB_E_NOAGGREGATION) { odtLog<<"Aggregation is not supported.\n"; tTestResult = TEST_SKIPPED; goto CLEANUP; } //Verify Aggregation for this rowset... TESTC(Aggregate.VerifyAggregationQI(hr, IID_IRowset)) tTestResult = TEST_PASS; CLEANUP: SAFE_RELEASE(pIUnkInner); return tTestResult; } //testAggregateRowset //---------------------------------------------------------------------- //@mfunc Use the IRowset interface to obtain the IRowsetIdentity //interface. Fetch the first 2 rows. If we can fetch backwards, then //fetch the second row again. Use the method IsSameRow to compare the //row handles. Verify the results. // TESTRESULT CQuickTest::testIRowsetIdentity() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; HROW* rghRows1 = NULL; HROW* rghRows2 = NULL; DBCOUNTITEM cRowsObtained1 = 0; DBCOUNTITEM cRowsObtained2 = 0; IRowsetIdentity* pIRId = NULL; if(m_ulMaxOpenRows == 0) m_ulMaxOpenRows = m_pTable->CountRowsOnTable(); //Obtain IRowsetIdentity interface. if(!VerifyInterface(m_pIRowset,IID_IRowsetIdentity, ROWSET_INTERFACE,(IUnknown**)&pIRId)) return TEST_FAIL; //Position cursor at beginning of rowset. TESTC_(RestartPosition(m_pIRowset), S_OK) //Fetch the first 2 rows. TEST2C_(hr = GetNextRows(m_pIRowset, NULL, 0, 2, &cRowsObtained1, (HROW **)&rghRows1), S_OK, DB_S_ROWLIMITEXCEEDED) if(hr==S_OK) { TESTC(cRowsObtained1==2 && rghRows1) } else { //hr is DB_S_ROWLIMITEXCEEDED. COMPARE(m_ulMaxOpenRows<2, TRUE); COMPARE(cRowsObtained1, 1); } //If we can fetch backwards, get the 2nd row again. if(m_fFetchBackwards &&(m_ulMaxOpenRows>2)) { //Use IRowset to get 2nd row again. TESTC_(hr = GetNextRows(m_pIRowset, NULL, 0, -1, &cRowsObtained2, (HROW **)&rghRows2), S_OK) //The 2nd row fetched first time is compared to the //2nd row fetched second time. CHECK(pIRId->IsSameRow(rghRows1[1], *rghRows2), S_OK); //The 1st row is compared to the 2nd row fetched second time. CHECK(pIRId->IsSameRow(rghRows1[0], *rghRows2), S_FALSE); } //Compare the 1st row with the 2nd row. if(cRowsObtained1 == 2) CHECK(pIRId->IsSameRow(rghRows1[0], rghRows1[1]), S_FALSE); //Compare the 1st row with itself. CHECK(pIRId->IsSameRow(rghRows1[0], rghRows1[0]), S_OK); tTestResult = TEST_PASS; CLEANUP: CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained1, &rghRows1), S_OK); CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained2, &rghRows2), S_OK); SAFE_RELEASE(pIRId); return tTestResult; } //testIRowsetIdentity //---------------------------------------------------------------------- //@mfunc Call the method RestartPosition. Then fetch all the rows in //the table (sequentially) one at a time (in the forward direction). //Compare data for that row and release it. Determine the MAXOPENROWS. //Restart position and open the maximum number of rows all at once. //Compare their data. Release them all. Call RestartPosition again. If //fetching backwards is supported, then skip 4 rows forward and fetch //backwards 3 rows. So we should get the 4th, 3rd and 2nd rows. Compare //their data and release them. // TESTRESULT CQuickTest::testIRowset() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRows = 0, cMultRows = 0; DBORDINAL cRowsetCols = 0; DB_LORDINAL* rgColumnsOrd = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create Accessor with a binding using length, //status and value. This accessor binds the Index //column also. TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Get list of ordinals. TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) //Get number of rows on table. cRows = m_pTable->CountRowsOnTable(); //Position cursor on first row. TESTC_(RestartPosition(m_pIRowset), S_OK) //Get one row at a time, compare and release. for(ulIndex=0; ulIndex= m_ulMaxOpenRows) cMultRows = m_ulMaxOpenRows; if(cRows < m_ulMaxOpenRows) cMultRows = cRows; if(m_ulMaxOpenRows == 0) cMultRows = cRows; //Restart position. TESTC_(RestartPosition(m_pIRowset), S_OK) //Now get multiple rows, compare and then release all. TESTC(GetDataAndCompare(0, cMultRows, 1, cRowsetCols, rgColumnsOrd, m_pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) //Restart position. TESTC_(RestartPosition(m_pIRowset), S_OK) //If fetch backwards is supported, then skip 2 rows and fetch //backwards 2 rows. We will get rows 2 and 1. Verify their data. if((cMultRows>4) && (m_fFetchBackwards)) TESTC(GetDataAndCompare(2, -2, 2, cRowsetCols, rgColumnsOrd, m_pIRowset, hAccessor, cBindings, rgBindings, cbRowSize)) tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); return tTestResult; } //testIRowset //---------------------------------------------------------------------- //@mfunc Check if Updateability and DBPROPVAL_UP_CHANGE are supported. //Create an accessor binds all updateable, non-index columns. Fetch the //first row. Set it's data. Call GetData on the first row. Verify the //data obtained is same as the one we had set. // TESTRESULT CQuickTest::testIRowsetChangeSet() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG_PTR updtFlag = 0; DBLENGTH cbRowSize = 0; DBORDINAL cRowsetCols = 0; DBCOUNTITEM cRowsObtained = 0; DB_LORDINAL* rgColumnsOrd = NULL; HROW* rghRows = NULL; BYTE* pData = NULL; BYTE* pData2 = NULL; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; IAccessor* pIAccessor = NULL; IRowsetChange* pIRC = NULL; if(!IsUsableInterface(ROWSET_INTERFACE, IID_IRowsetChange)) { odtLog<GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create Accessor with a binding using length, status and value. //This accessor binds all updateable non-index columns. TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Restart position. TESTC_(RestartPosition(m_pIRowset), S_OK) //Allocate 2 new data buffers SAFE_ALLOC(pData, BYTE, cbRowSize) SAFE_ALLOC(pData2, BYTE, cbRowSize) memset(pData, 0, (size_t) cbRowSize); memset(pData2, 0, (size_t) cbRowSize); //Get the first row. TESTC_(GetNextRows(m_pIRowset, NULL,0,1,&cRowsObtained, &rghRows),S_OK) //Make data corresponding to row (g_ulNextRow+1). TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA, cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols, rgColumnsOrd, PRIMARY),S_OK) //Set data of first row. TESTC_(hr=pIRC->SetData(rghRows[0],hAccessor,pData),S_OK) //Get the data for the first row TESTC_(m_pIRowset->GetData(rghRows[0],hAccessor,pData2),S_OK) //make sure GetData should be able to see the change TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings, m_pIMalloc,TRUE, FALSE, COMPARE_ONLY)) tTestResult = TEST_PASS; CLEANUP: ReleaseInputBindingsMemory(cBindings, rgBindings, pData, TRUE); ReleaseInputBindingsMemory(cBindings, rgBindings, pData2, TRUE); PROVIDER_FREE(rgColumnsOrd); CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRC); return tTestResult; } //testIRowsetChangeSet //---------------------------------------------------------------------- //@mfunc @mfunc Check if Updateability and DBPROPVAL_UP_DELETE are //supported. Delete the first row. Make sure it was deleted. // TESTRESULT CQuickTest::testIRowsetChangeDelete() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG_PTR updtFlag = 0; DBLENGTH cbRowSize = 0; DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; DBROWSTATUS rgRowStatus[1]; BYTE* pData = NULL; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; IAccessor* pIAccessor = NULL; IRowsetChange* pIRC = NULL; if(!IsUsableInterface(ROWSET_INTERFACE, IID_IRowsetChange)) { odtLog<DeleteRows(NULL,1,rghRows,rgRowStatus), S_OK) m_pTable->SubtractRow(); TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK) SAFE_ALLOC(pData, BYTE, cbRowSize) //Call GetData on the deleted row. This should fail. hr = m_pIRowset->GetData(rghRows[0], hAccessor, pData); CHECKW(hr, DB_E_DELETEDROW); tTestResult = TEST_PASS; CLEANUP: SAFE_FREE(pData); CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRC); return tTestResult; } //testIRowsetChangeDelete //---------------------------------------------------------------------- //@mfunc Check if Updateability and DBPROPVAL_UP_INSERT are supported. //Create an accessor binds all updateable, non-index columns. Create //data for a new row and insert it. Verify that the new row was inserted //into the rowset. // TESTRESULT CQuickTest::testIRowsetChangeInsert() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG_PTR updtFlag = 0; DBORDINAL cRowsetCols = 0; ULONG cRowsInserted = 0; //small no. DB_LORDINAL* rgColumnsOrd = NULL; HROW hNewRow = DB_NULL_HROW; BYTE* pData = NULL; BYTE* pData2 = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; IAccessor* pIAccessor = NULL; IRowsetChange* pIRC = NULL; if(!IsUsableInterface(ROWSET_INTERFACE, IID_IRowsetChange)) { odtLog<GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) TESTC(VerifyInterface(m_pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create Accessor with a binding using length, status and value. //This accessor binds all updateable non-index columns. TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, UPDATEABLE_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Restart position. TESTC_(RestartPosition(m_pIRowset), S_OK) //Allocate 2 new data buffers SAFE_ALLOC(pData, BYTE, cbRowSize) SAFE_ALLOC(pData2, BYTE, cbRowSize) memset(pData, 0, (size_t) cbRowSize); memset(pData2, 0, (size_t) cbRowSize); //Make data corresponding to row (g_ulNextRow+1). TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA, cBindings, rgBindings, &pData,++g_ulNextRow, cRowsetCols, rgColumnsOrd, PRIMARY),S_OK) //Insert the row. TESTC_(pIRC->InsertRow(NULL,hAccessor,pData,&hNewRow),S_OK) TESTC(hNewRow != DB_NULL_HROW) m_pTable->AddRow(); cRowsInserted++; //get the data for the new row TESTC_(m_pIRowset->GetData(hNewRow,hAccessor,pData2),S_OK) //Compare the data. TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings, m_pIMalloc,TRUE, FALSE, COMPARE_ONLY)) tTestResult = TEST_PASS; CLEANUP: ReleaseInputBindingsMemory(cBindings, rgBindings, pData, TRUE); ReleaseInputBindingsMemory(cBindings, rgBindings, pData2, TRUE); PROVIDER_FREE(rgColumnsOrd); CHECK(m_pIRowset->ReleaseRows(cRowsInserted, &hNewRow, NULL,NULL, NULL), S_OK); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRC); return tTestResult; } //testIRowsetChangeInsert //---------------------------------------------------------------------- //@mfunc Create a rowset with IRowsetUpdate. Modify the rowset. Use the //methods of IRowsetUpdate to Undo and Update changes. Verify results //of the various methods of this interface. // TESTRESULT CQuickTest::testIRowsetUpdate() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG_PTR updtFlag = 0; DBCOUNTITEM cRowsObtained = 0; DBORDINAL cRowsetCols = 0; DB_LORDINAL* rgColumnsOrd = NULL; HROW* rghRows = NULL; BYTE* pData = NULL; BYTE* pData2 = NULL; BYTE* pOrgData = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; DBCOUNTITEM cRowsOut = 0; DBCOUNTITEM cPendingRows = 0; HROW* rghRowsOut = NULL; HROW* rgPendingRows = NULL; DBROWSTATUS* rgRowStatus = NULL; DBPENDINGSTATUS pendingStatus = DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_CHANGED | DBPENDINGSTATUS_DELETED ; DBPENDINGSTATUS* rgPendingStatus = NULL; IRowset* pIRowset = NULL; IAccessor* pIAccessor = NULL; IRowsetUpdate* pIRowsetUpdate = NULL; FreeProperties(&m_cPropSets, &m_rgPropSets); LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE| DBPROPVAL_UP_DELETE| DBPROPVAL_UP_INSERT ; //Set the following properties (ALL REQUIRED). SetProperty(DBPROP_IRowsetUpdate, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets); SetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; //Open a rowset with above properties set. hr=CreateOpenRowset(m_pTable, IID_IRowset, (IUnknown**)&pIRowset); if(hr==DB_E_ERRORSOCCURRED) { DumpPropertyErrors(m_cPropSets, m_rgPropSets); FreeProperties(&m_cPropSets, &m_rgPropSets); TESTC(!pIRowset) return TEST_SKIPPED; } TEST2C_(hr, S_OK, DB_S_ERRORSOCCURRED) //Get value of the DBPROP_UPDATABILITY property. if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*) pIRowset, &updtFlag)) { odtLog<GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) TESTC(VerifyInterface(pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) TESTC(VerifyInterface(pIRowset,IID_IRowsetUpdate, ROWSET_INTERFACE,(IUnknown**)&pIRowsetUpdate)) //Create Accessor with a binding using length, status and value. //This accessor binds all updateable non-index columns. TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Donot call RestartPosition. We should be at the beginning of //the rowset. //Allocate 2 new data buffers SAFE_ALLOC(pData, BYTE, cbRowSize) SAFE_ALLOC(pData2, BYTE, cbRowSize) SAFE_ALLOC(pOrgData, BYTE, cbRowSize) memset(pData, 0, (size_t) cbRowSize); memset(pData2, 0, (size_t) cbRowSize); memset(pOrgData, 0, (size_t) cbRowSize); //Fetch the 2nd row. TESTC_(hr = GetNextRows(pIRowset, NULL,1,1,&cRowsObtained, &rghRows),S_OK) TESTC_(hr = pIRowset->GetData(rghRows[0],hAccessor,pOrgData),S_OK) //Make data corresponding to row (g_ulNextRow+1). TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA, cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols, rgColumnsOrd, PRIMARY),S_OK) //Set data of 2nd row. TESTC_(hr = pIRowsetUpdate->SetData(rghRows[0],hAccessor,pData),S_OK) //GetPendingRows should return the 2nd row. TESTC_(hr = pIRowsetUpdate->GetPendingRows(NULL, pendingStatus, &cPendingRows, &rgPendingRows, &rgPendingStatus), S_OK) //Check return values. Pending status should be _CHANGED. TESTC(cPendingRows==1 && rgPendingRows && rgPendingStatus) TESTC(rgPendingRows[0] != DB_NULL_HROW) TESTC(rgPendingStatus[0] == DBPENDINGSTATUS_CHANGED) rgPendingStatus[0] = DBPENDINGSTATUS_INVALIDROW; //Call GetRowsStatus on rgPendingRows obtained from the call //to GetPendingRows. Pending status should be _CHANGED. TESTC_(hr = pIRowsetUpdate->GetRowStatus(NULL, 1, rgPendingRows, rgPendingStatus), S_OK) TESTC(rgPendingStatus[0] == DBPENDINGSTATUS_CHANGED) PROVIDER_FREE(rgPendingRows); PROVIDER_FREE(rgPendingStatus); //Get data for the 2nd row. TESTC_(hr = pIRowset->GetData(rghRows[0],hAccessor,pData2),S_OK) //The data should be the new one we had set it to. TESTC(CompareData(cRowsetCols, rgColumnsOrd, g_ulNextRow, pData2, cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY, COMPARE_ONLY)) ReleaseInputBindingsMemory(cBindings, rgBindings, pData); ReleaseInputBindingsMemory(cBindings, rgBindings, pData2); memset(pData, 0, (size_t) cbRowSize); memset(pData2, 0, (size_t) cbRowSize); //This should return the original data for the 2nd row. TESTC_(hr = pIRowsetUpdate->GetOriginalData(rghRows[0], hAccessor, pData2), S_OK) //Make sure it is the orginal data. TESTC(CompareBuffer(pOrgData,pData2,cBindings,rgBindings, m_pIMalloc,TRUE, FALSE, COMPARE_ONLY)) //Undo the change made to the 2nd row. TESTC_(hr = pIRowsetUpdate->Undo(NULL, 1, rghRows, &cRowsOut, &rghRowsOut, &rgRowStatus), S_OK) TESTC(cRowsOut==1 && rghRowsOut && rgRowStatus && rgRowStatus[0]==DBROWSTATUS_S_OK) TESTC(rghRowsOut[0] != DB_NULL_HROW) //Get the data after undoing the change. TESTC_(hr = pIRowset->GetData(rghRowsOut[0],hAccessor,pData),S_OK) //This should be the same as the original data for 2nd row. TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings, m_pIMalloc,TRUE, FALSE, COMPARE_ONLY)) PROVIDER_FREE(rghRowsOut); PROVIDER_FREE(rgRowStatus); ReleaseInputBindingsMemory(cBindings, rgBindings, pData); ReleaseInputBindingsMemory(cBindings, rgBindings, pData2); memset(pData, 0, (size_t) cbRowSize); memset(pData2, 0, (size_t) cbRowSize); //Release the row handle. CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); //Get the 3rd row. TESTC_(hr = GetNextRows(pIRowset, NULL,0,1,&cRowsObtained, &rghRows),S_OK) //Delete the 3rd row. TESTC_(pIRowsetUpdate->DeleteRows(NULL,1,rghRows,rgRowStatus), S_OK) //GetPendingRows should give 1 row with status _DELETED. TESTC_(hr = pIRowsetUpdate->GetPendingRows(NULL, pendingStatus, &cPendingRows, &rgPendingRows, &rgPendingStatus), S_OK) TESTC(cPendingRows==1 && rgPendingRows && rgPendingStatus) TESTC(rgPendingStatus[0] == DBPENDINGSTATUS_DELETED) //Update the change. TESTC_(hr = pIRowsetUpdate->Update(NULL, 1, rghRows, &cRowsOut, &rghRowsOut,&rgRowStatus), S_OK) TESTC(cRowsOut==1 && rghRowsOut && rgRowStatus) TESTC(rghRowsOut[0] != DB_NULL_HROW) TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK) //Try to call GetData on the row which was deleted and updated. //This should fail. The expected return code is DB_E_DELETEDROW, //although this is provider specific. hr = pIRowset->GetData(rghRows[0],hAccessor,pData) ; CHECKW(hr, DB_E_DELETEDROW) ; cRowsObtained = 0; tTestResult = TEST_PASS; CLEANUP: ReleaseInputBindingsMemory(cBindings, rgBindings, pOrgData); FreeProperties(&m_cPropSets, &m_rgPropSets); SAFE_FREE(pData); SAFE_FREE(pData2); SAFE_FREE(pOrgData); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); PROVIDER_FREE(rgRowStatus); PROVIDER_FREE(rghRowsOut); PROVIDER_FREE(rgPendingRows); PROVIDER_FREE(rgPendingStatus); PROVIDER_FREE(rgColumnsOrd); SAFE_RELEASE(pIAccessor); SAFE_RELEASE(pIRowsetUpdate); SAFE_RELEASE(pIRowset); return tTestResult; } //testIRowsetUpdate //---------------------------------------------------------------------- //@mfunc Open 2 rowsets on the same table. Fetch the first rows of each //rowset and keep the row handles. Call SetData to modify the data of //the first row of rowset1. Then call IRowsetResynch::ResynchRows on //rowset2. Now the data of rowset2 should reflect the change made in //rowset1. Verify this. // TESTRESULT CQuickTest::testIRowsetResynch() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBCOUNTITEM cRowsObtained1 = 0; DBCOUNTITEM cRowsObtained2 = 0; DBCOUNTITEM cRowsOut = 0; ULONG_PTR updtFlag = 0; HROW* rghRows1 = NULL; HROW* rghRows2 = NULL; HROW* rghRowsOut = NULL; DBORDINAL cRowsetCols = 0; DB_LORDINAL* rgColumnsOrd = NULL; BYTE* pData = NULL; BYTE* pData2 = NULL; DBROWSTATUS* rgRowStatus = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; IRowset* pIRowset1 = NULL; IRowset* pIRowset2 = NULL; IAccessor* pIAccessor = NULL; IRowsetUpdate* pIRowsetUpdate = NULL; IRowsetChange* pIRowsetChange = NULL; IRowsetResynch* pIRowsetResynch = NULL; FreeProperties(&m_cPropSets, &m_rgPropSets); LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE| DBPROPVAL_UP_DELETE| DBPROPVAL_UP_INSERT ; //Set the following properties. SetProperty(DBPROP_IRowsetResynch, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; SetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; SetSettableProperty(DBPROP_OTHERUPDATEDELETE, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; SetSettableProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; //Open a rowset with above properties set. hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**) &pIRowset1); if(hr==DB_E_ERRORSOCCURRED) { DumpPropertyErrors(m_cPropSets, m_rgPropSets); FreeProperties(&m_cPropSets, &m_rgPropSets); TESTC(!pIRowset1) return TEST_SKIPPED; } TEST2C_(hr, S_OK, DB_S_ERRORSOCCURRED) //Get value of the DBPROP_UPDATABILITY property. if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*) pIRowset1, &updtFlag)) { odtLog<GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) //Allocate 2 new data buffers SAFE_ALLOC(pData, BYTE, cbRowSize) SAFE_ALLOC(pData2, BYTE, cbRowSize) memset(pData, 0, (size_t) cbRowSize); memset(pData2, 0, (size_t) cbRowSize); //Restart position for rowset1. TESTC_(RestartPosition(pIRowset1), S_OK) //Fetch first row of rowset1. TESTC_(hr = GetNextRows(pIRowset1, NULL,0,1,&cRowsObtained1, &rghRows1),S_OK) //Restart position for rowset2. TESTC_(RestartPosition(pIRowset2), S_OK) //Fetch first row of rowset2. TESTC_(hr = GetNextRows(pIRowset2, NULL,0,1,&cRowsObtained2, &rghRows2),S_OK) //Make data corresponding to row (g_ulNextRow+1). TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA, cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols, rgColumnsOrd, PRIMARY),S_OK) //Set data of 1st row of rowset1 to that of row (cTotalRows+1). TESTC_(hr = pIRowsetChange->SetData(rghRows1[0],hAccessor,pData),S_OK) //Release accessor and bindings. FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); TESTC(VerifyInterface(pIRowset2,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create Accessor with a binding using length, status and value. //This accessor binds the updateable non-index columns. TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Get the backend data for first row of rowset2. TESTC_(hr = pIRowsetResynch->GetVisibleData(rghRows2[0], hAccessor, pData2), S_OK) //This should be same as the new data that the first row of rowset1 //was set to. TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings, m_pIMalloc,TRUE, FALSE, COMPARE_ONLY)) ReleaseInputBindingsMemory(cBindings, rgBindings, pData2); memset(pData2, 0, (size_t) cbRowSize); //Resynch the rows of rowset2. TESTC_(hr = pIRowsetResynch->ResynchRows(1, rghRows2, &cRowsOut, &rghRowsOut, &rgRowStatus), S_OK) TESTC(cRowsOut==1 && rghRowsOut && rgRowStatus) TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK) //Get the data for the first row of rowset2. TESTC_(hr = pIRowset2->GetData(rghRowsOut[0], hAccessor, pData2), S_OK) //It should be the same as the data which was set in rowset1. TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings, m_pIMalloc,TRUE, FALSE, COMPARE_ONLY)) tTestResult = TEST_PASS; CLEANUP: FreeProperties(&m_cPropSets, &m_rgPropSets); ReleaseInputBindingsMemory(cBindings, rgBindings, pData, TRUE); ReleaseInputBindingsMemory(cBindings, rgBindings, pData2, TRUE); CHECK(ReleaseRows(&pIRowset1, &cRowsObtained1, &rghRows1), S_OK); CHECK(ReleaseRows(&pIRowset2, &cRowsObtained2, &rghRows2), S_OK); PROVIDER_FREE(rghRowsOut); PROVIDER_FREE(rgRowStatus); PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetUpdate); SAFE_RELEASE(pIRowsetChange); SAFE_RELEASE(pIRowset1); SAFE_RELEASE(pIRowset2); SAFE_RELEASE(pIRowsetResynch); return tTestResult; } //testIRowsetResynch //---------------------------------------------------------------------- //@mfunc Open a rowset with IRowsetRefresh (in the buffered update mode). //Fetch the first row of the rowset and keep the row handle. Call //SetData to modify the data of the first row. Then, without calling //IRowsetUpdate::Update, call IRowsetRefresh::RefreshVisibleData. Then //call GetData on the first row. This should give the original data //corresponding to the first row. // TESTRESULT CQuickTest::testIRowsetRefresh() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBCOUNTITEM cRowsObtained = 0; DBCOUNTITEM cRowsOut = 0; ULONG_PTR updtFlag = 0; HROW* rghRows = NULL; HROW* rghRowsOut = NULL; DBORDINAL cRowsetCols = 0; DB_LORDINAL* rgColumnsOrd = NULL; BYTE* pData = NULL; BYTE* pOrgData = NULL; BYTE* pData2 = NULL; DBROWSTATUS* rgRowStatus = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; IRowset* pIRowset = NULL; IAccessor* pIAccessor = NULL; IRowsetUpdate* pIRowsetUpdate = NULL; IRowsetRefresh* pIRowsetRefresh = NULL; FreeProperties(&m_cPropSets, &m_rgPropSets); LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE| DBPROPVAL_UP_DELETE| DBPROPVAL_UP_INSERT ; //Set the following properties. SetProperty(DBPROP_IRowsetRefresh, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; SetProperty(DBPROP_IRowsetUpdate, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_REQUIRED) ; SetSettableProperty(DBPROP_OTHERUPDATEDELETE, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; SetSettableProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; //Open a rowset with above properties set. hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)&pIRowset); if(hr==DB_E_ERRORSOCCURRED) { DumpPropertyErrors(m_cPropSets, m_rgPropSets); FreeProperties(&m_cPropSets, &m_rgPropSets); TESTC(!pIRowset); tTestResult = TEST_SKIPPED; goto CLEANUP; } TEST2C_(hr, S_OK, DB_S_ERRORSOCCURRED) //Get value of the DBPROP_UPDATABILITY property. if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*) pIRowset, &updtFlag)) { odtLog<GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) //Allocate 2 new data buffers SAFE_ALLOC(pData, BYTE, cbRowSize) SAFE_ALLOC(pData2, BYTE, cbRowSize) SAFE_ALLOC(pOrgData, BYTE, cbRowSize) memset(pData, 0, (size_t) cbRowSize); memset(pData2, 0, (size_t) cbRowSize); memset(pOrgData, 0, (size_t) cbRowSize); //Restart position. TESTC_(RestartPosition(pIRowset), S_OK) //Fetch first row. TESTC_(hr = GetNextRows(pIRowset, NULL,0,1,&cRowsObtained, &rghRows),S_OK) //Get data of the first row. TESTC_(hr = pIRowset->GetData(rghRows[0], hAccessor, pOrgData), S_OK) //Make data corresponding to row (g_ulNextRow+1). TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA, cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols, rgColumnsOrd, PRIMARY),S_OK) //Set data of 1st row. TESTC_(hr = pIRowsetUpdate->SetData(rghRows[0],hAccessor,pData),S_OK) //Get the backend data for first row. TESTC_(hr = pIRowsetRefresh->GetLastVisibleData(rghRows[0], hAccessor, pData2), S_OK) //This should be same as the original data of first row. TESTC(CompareBuffer(pData2,pOrgData,cBindings,rgBindings, m_pIMalloc,TRUE, FALSE, COMPARE_ONLY)) ReleaseInputBindingsMemory(cBindings, rgBindings, pData2); memset(pData2, 0, (size_t) cbRowSize); //Resynch the first row. TESTC_(hr = pIRowsetRefresh->RefreshVisibleData(NULL, 1, rghRows, TRUE, &cRowsOut, &rghRowsOut, &rgRowStatus), S_OK) TESTC(cRowsOut==1 && rghRowsOut && rgRowStatus) TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK) //Get the data for the first row. TESTC_(hr = pIRowset->GetData(rghRowsOut[0], hAccessor, pData2), S_OK) //It should be the same as the original data of first row. TESTC(CompareBuffer(pData2,pOrgData,cBindings,rgBindings, m_pIMalloc,TRUE, FALSE, COMPARE_ONLY)) tTestResult = TEST_PASS; CLEANUP: FreeProperties(&m_cPropSets, &m_rgPropSets); ReleaseInputBindingsMemory(cBindings, rgBindings, pData, TRUE); ReleaseInputBindingsMemory(cBindings, rgBindings, pData2, TRUE); ReleaseInputBindingsMemory(cBindings, rgBindings, pOrgData, TRUE); CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); PROVIDER_FREE(rghRowsOut); PROVIDER_FREE(rgRowStatus); PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetUpdate); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIRowsetRefresh); return tTestResult; } //testIRowsetRefresh //----------------------------------------------------------------------- //@mfunc Obtain the IAccesssor interface through the ICommand interface. //Create bindings and then create an accessor with this binding. The //length, status and value fields are bound. All columns are bound //including BLOB_LONG. Verify the status of the bindings after creating //the accessor. Then call the method GetBindings and verify that //they are the same as the ones used to create the accessor. Use the //accessor to fetch rows and verify them. Call ReleaseAccessor. // TESTRESULT CQuickTest::testCmdIAccessor() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRows = 0; DBROWCOUNT cRowsAffected = 0; DBORDINAL cRowsetCols = 0; DB_LORDINAL* rgColumnsOrd = NULL; DBBINDSTATUS* rgStatus = NULL; DBLENGTH cbRowSize = 0; ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; IRowset* pIRowset = NULL; ICommand* pICommand = NULL; //Set this property. SetSettableProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET, &cPropSets, &rgPropSets) ; //Create SQL stmt and set command text. TEST2C_(hr = m_pTable->ExecuteCommand(SELECT_ALLFROMTBL, IID_ICommand, NULL, NULL, &cRowsetCols, &rgColumnsOrd, EXECUTE_NEVER, cPropSets, rgPropSets, NULL, NULL, &pICommand), S_OK, DB_S_ERRORSOCCURRED) TESTC(pICommand != NULL) //Obtain the IAccessor (command) interface. if(!VerifyInterface(pICommand,IID_IAccessor, COMMAND_INTERFACE,(IUnknown**)&pIAccessor)) return TEST_FAIL; //Create Accessor with a binding using length, status and value. //All columns are bound including BLOB_LONG. TESTC_(hr = GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA, &hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL, NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG, &rgStatus),S_OK) //Verify status of bindings. for(ulIndex=0; ulIndexExecute(NULL, IID_IRowset, NULL, &cRowsAffected, (IUnknown**)&pIRowset), S_OK) TESTC(pIRowset != NULL) //Get number of rows. cRows = m_pTable->CountRowsOnTable(); //Make sure we are on the first row. TESTC_(RestartPosition(pIRowset), S_OK) //For each row in the table, fetch the row, compare the data in the //row and release the row. for(ulIndex=0; ulIndexSetProperties(m_cPropSets, m_rgPropSets), S_OK, DB_S_ERRORSOCCURRED) //Loop through all the properties. for(ulIndex=0; ulIndex < m_rgPropSets[0].cProperties; ulIndex++) { //If status shows DBPROPSTATUS_OK then make sure the value //of that property was set to VARIANT_TRUE. the hr in this //case has to be either S_OK or DB_S_ERRORSOCCURRED. if(m_rgPropSets[0].rgProperties[ulIndex].dwStatus == DBPROPSTATUS_OK) { COMPARE(GetProperty(m_rgPropSets[0].rgProperties[ulIndex].dwPropertyID, m_rgPropSets[0].guidPropertySet, pICommProp), TRUE); if(hr==DB_S_ERRORSOCCURRED) usSupported++; else TESTC_(hr, S_OK) } //If return value was DB_S_ERRORSOCCURRED then..... if(hr==DB_S_ERRORSOCCURRED) { //If status shows DBPROPSTATUS_NOTSUPPORTED then make sure //that the property is not supported. if(m_rgPropSets[0].rgProperties[ulIndex].dwStatus == DBPROPSTATUS_NOTSUPPORTED) { COMPARE(SupportedProperty(m_rgPropSets[0].rgProperties[ulIndex].dwPropertyID, m_rgPropSets[0].guidPropertySet), FALSE); } //If the status shows DBPROPSTATUS_NOTSETTABLE then make sure //that the property is not settable. else if(m_rgPropSets[0].rgProperties[ulIndex].dwStatus == DBPROPSTATUS_NOTSETTABLE) { COMPARE(SettableProperty(m_rgPropSets[0].rgProperties[ulIndex].dwPropertyID, m_rgPropSets[0].guidPropertySet), FALSE); } } } //If DB_S_ERRORSOCCURRED was returned, then the number of properties //set successfully should be >0 and 0 && usSupportedCreateCommand(NULL, IID_ICommandText, (IUnknown**)&pICT), S_OK) //Create the following SQL Stmt. TESTC(SUCCEEDED(m_pTable->CreateSQLStmt(SELECT_UPDATEABLE, NULL, &pSQLSet, NULL, NULL))) //Set the command text to the above SQL stmt. TESTC_(pICT->SetCommandText(DBGUID_DEFAULT, pSQLSet), S_OK) //Get the command text. TEST2C_(hr = pICT->GetCommandText(&guidDialect, &pSQLGet), S_OK, DB_S_DIALECTIGNORED) //Verify that SQL stmt got is the same that was used to set the //command text. TESTC(wcscmp(pSQLSet, pSQLGet) == 0) //Free command text PROVIDER_FREE(pSQLSet); PROVIDER_FREE(pSQLGet); //Create another SQL Stmt. TESTC(SUCCEEDED(m_pTable->CreateSQLStmt(SELECT_ALLFROMTBL,NULL, &pSQLSet,NULL,NULL))) //Set the command text to the above SQL stmt. TESTC_(pICT->SetCommandText(DBGUID_DEFAULT, pSQLSet), S_OK) //If ICommandPrepare is supported, prepare the command. //It is not required to prepare the command for Execute. if(VerifyInterface(pICT,IID_ICommandPrepare, COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare)) { TESTC(pICommandPrepare->Prepare(1) == S_OK) } //Execute the command. cRowsAffected is undefined on output. TESTC_(pICT->Execute(NULL, IID_NULL, NULL, &cRowsAffected, NULL),S_OK) //Get the command text after command execution. TEST2C_(hr = pICT->GetCommandText(&guidDialect, &pSQLGet), S_OK, DB_S_DIALECTIGNORED) //Verify that SQL stmt got is the same that was used to set the //command text before execution. TESTC(wcscmp(pSQLSet, pSQLGet) == 0) tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(pSQLSet); PROVIDER_FREE(pSQLGet); SAFE_RELEASE(pICommandPrepare); SAFE_RELEASE(pICT); return tTestResult; } //testICmdText //---------------------------------------------------------------------- //@mfunc Create a command on the session. Call the GetDBSession method //to obtain the IOpenRowset interface. S_FALSE may be returned by this //method if the provider did not have an object that created the command. //If S_OK is returned, verify the interface obtained. Set the command //text and execute it asking for the IRowsetInfo interface. Call the //GetSpecification method on it to obtain the ICommand interface. Verify //that it should be the same as the first command interface. Call //GetDBSession again, this time to get IDBCreateCommand. Verify this //interface. // TESTRESULT CQuickTest::testICmdGetDBSession() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ICommand* pICmd1 = NULL; ICommand* pICmd2 = NULL; IOpenRowset* pIOR = NULL; IRowsetInfo* pIRowsetInfo = NULL; IDBCreateCommand* pIDBCC = NULL; //Create a command object and get the ICommand interface. TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand, (IUnknown**)&pICmd1), S_OK) //Call the GetDBSession method. TEST2C_(hr = pICmd1->GetDBSession(IID_IOpenRowset, (IUnknown**)&pIOR), S_OK, S_FALSE) if(hr==S_FALSE) { COMPARE(pIOR, NULL); //Issue a warning. odtLog<Execute(NULL,IID_IRowsetInfo, NULL, NULL, (IUnknown**)&pIRowsetInfo), S_OK) //Call GetSpecification method of IRowsetInfo. TEST2C_(hr = pIRowsetInfo->GetSpecification(IID_ICommand, (IUnknown**) &pICmd2), S_OK, S_FALSE) if(hr==S_FALSE) { COMPARE(pICmd2, NULL); //Issue a warning. odtLog<GetDBSession(IID_IDBCreateCommand, (IUnknown**) &pIDBCC) ; if(m_hr==S_FALSE) { //Issue a warning. odtLog<CreateCommand(NULL, IID_ICommandText, (IUnknown**)&pICmd1), S_OK) if(!fIsProvReadOnly) { //Set the command text to insert. TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL,eINSERT, NO_QUERY, NULL,NULL,NULL,NULL,&pwszCmdText), S_OK) //Execute the command. TEST2C_(hr=pICmd1->Execute(NULL, IID_NULL, NULL, &cRowsAffected, NULL),S_OK, DB_E_NOCOMMAND) if(pwszCmdText) { TESTC_(hr, S_OK) //Check affected rows. TESTC(cRowsAffected==1 || cRowsAffected==DB_COUNTUNAVAILABLE) //Insert adds a row. m_pTable->AddRow(); } else TESTC_(hr, DB_E_NOCOMMAND) SAFE_FREE(pwszCmdText); //Set the command text to insert again. The command text has to //be set again to insert a unique row. TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL,eINSERT, NO_QUERY, NULL,NULL,NULL,NULL,&pwszCmdText), S_OK) //Execute the command. TEST2C_(hr=pICmd1->Execute(NULL, IID_NULL, NULL, &cRowsAffected, NULL),S_OK, DB_E_NOCOMMAND) if(pwszCmdText) { TESTC_(hr, S_OK) //Check affected rows. TESTC(cRowsAffected==1 || cRowsAffected==DB_COUNTUNAVAILABLE) //Insert adds a row. m_pTable->AddRow(); } else TESTC_(hr, DB_E_NOCOMMAND) } //Set command text to select all from table. TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL, eSELECT, SELECT_ALLFROMTBL, NULL), S_OK) //Execute this command. TESTC_(hr=pICmd1->Execute(NULL, IID_IRowset, NULL,NULL, (IUnknown**) &pIRowset),S_OK) //Verify that pIRowset is not NULL. TESTC(pIRowset != NULL) //Obtain the ICommandProperties interface. TESTC(VerifyInterface(pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) cTotalRows = m_pTable->CountRowsOnTable(); //Create Accessor with a binding using length, status and value. TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA, &hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL, NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS), S_OK) //Get list of ordinals. TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) //Get data from the rowset and verify. for(ulIndex=0; ulIndexCreateCommand(NULL, IID_ICommand, (IUnknown**)&pICmd1), S_OK) //Set the command text to select all from table. TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL, eSELECT, SELECT_ALLFROMTBL, NULL), S_OK) //If ICommandPrepare is supported, prepare the command (Not required) if(VerifyInterface(pICmd1,IID_ICommandPrepare, COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare)) { TESTC(pICommandPrepare->Prepare(3) == S_OK) } cTotalRows = m_pTable->CountRowsOnTable(); //Execute the command, not requesting any interface. cRowsAffected //is undefined on output. CHECK(hr=pICmd1->Execute(NULL, IID_NULL, NULL, &cRowsAffected, NULL),S_OK); //Execute command again, requesting an IRowset interface. CHECK(hr=pICmd1->Execute(NULL, IID_IRowset, NULL,NULL, (IUnknown**) &pIRowset),S_OK); //Execute command again, requesting an IRowsetInfo interface. CHECK(hr=pICmd1->Execute(NULL, IID_IRowsetInfo, NULL,NULL, (IUnknown**) &pIRowsetInfo),S_OK); //Verify that the 2 interfaces returned are not for the same rowset //object. COMPARE(VerifyEqualInterface(pIRowset, pIRowsetInfo), FALSE); tTestResult = TEST_PASS; CLEANUP: SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIRowsetInfo); SAFE_RELEASE(pICommandPrepare); SAFE_RELEASE(pICmd1); return tTestResult; } //testICmdExec2 //---------------------------------------------------------------------- //@mfunc Call prepare without having set the command text. This should //fail. Set the command text to select all from table. Call //GetColumnInfo before preparing the command. Check for expected return //code. Then execute the command to open a rowset. Calling Prepare now //should fail again as the rowset object is open. Now release the rowset, //prepare the command and then call GetColumnInfo. It should succeed //this time. // TESTRESULT CQuickTest::testCmdPrep() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBORDINAL cColumns = 0; WCHAR* pStringsBuffer = NULL; DBCOLUMNINFO* rgInfo = NULL; IRowset* pIRowset = NULL; IColumnsInfo* pIColumnsInfo = NULL; ICommand* pICmd1 = NULL; ICommandPrepare* pICommandPrepare = NULL; //Create a command object. TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand, (IUnknown**)&pICmd1), S_OK) if(!VerifyInterface(pICmd1,IID_ICommandPrepare, COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare)) { odtLog<Prepare(1), DB_E_NOCOMMAND) //Set the command text to select all from table. TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL, eSELECT, SELECT_ALLFROMTBL, NULL), S_OK) TESTC(VerifyInterface(pICmd1,IID_IColumnsInfo, COMMAND_INTERFACE,(IUnknown**)&pIColumnsInfo)) //Call GetColumnInfo without preparing the command. TESTC_(pIColumnsInfo->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer) ,DB_E_NOTPREPARED) //Execute the command to open a rowset. TESTC_(hr=pICmd1->Execute(NULL, IID_IRowset, NULL,NULL, (IUnknown**) &pIRowset),S_OK) //Call Prepare with the rowset open. TESTC_(hr=pICommandPrepare->Prepare(1), DB_E_OBJECTOPEN) //Release the rowset. SAFE_RELEASE(pIRowset); //Prepare the command. TESTC_(hr=pICommandPrepare->Prepare(1), S_OK) //Call GetColumnInfo. This should succeed. TESTC_(pIColumnsInfo->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer) ,S_OK) TESTC(cColumns>0 && rgInfo && pStringsBuffer) tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgInfo); PROVIDER_FREE(pStringsBuffer); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIColumnsInfo); SAFE_RELEASE(pICommandPrepare); SAFE_RELEASE(pICmd1); return tTestResult; } //testCmdPrep //---------------------------------------------------------------------- //@mfunc Set the command text to select all from table. Call Unprepare. //This should succeed. Now prepare the command and execute it to open //a rowset. Calling Unprepare now would fail due to the rowset being //open. Now release the rowset and then call Unprepare. // TESTRESULT CQuickTest::testCmdUnprep() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; IRowset* pIRowset = NULL; ICommand* pICmd1 = NULL; ICommandPrepare* pICommandPrepare = NULL; //Create a command object. TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand, (IUnknown**)&pICmd1), S_OK) if(!VerifyInterface(pICmd1,IID_ICommandPrepare, COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare)) { odtLog<Unprepare(), S_OK) //Prepare the command. TESTC_(hr=pICommandPrepare->Prepare(1), S_OK) //Execute the command TESTC_(hr=pICmd1->Execute(NULL, IID_IRowset, NULL,NULL, (IUnknown**) &pIRowset),S_OK) //Unprepare should fail as the rowset is open. TESTC_(hr=pICommandPrepare->Unprepare(), DB_E_OBJECTOPEN) //Release the rowset. SAFE_RELEASE(pIRowset); //Now Unprepare should succeed. TESTC_(hr=pICommandPrepare->Unprepare(), S_OK) tTestResult = TEST_PASS; CLEANUP: SAFE_RELEASE(pIRowset); SAFE_RELEASE(pICommandPrepare); SAFE_RELEASE(pICmd1); return tTestResult; } //testCmdUnprep //---------------------------------------------------------------------- //@mfunc Make the parameter bindings to be used in testICmdWParam. // BOOL CQuickTest::MakeParamBindings( CTable* pTable, DBORDINAL cColumnsOnTable, DBORDINAL* pcParamColMap, LONG_PTR* rgParamColMap, DB_UPARAMS* pcDbParamBindInfo, DBPARAMBINDINFO* rgDbParamBindInfo, DB_UPARAMS* rgParamOrdinals, DBCOLUMNINFO* rgTableInfo ) { DBORDINAL ulIndex; BOOL bSuccess = FALSE; DBORDINAL ulSearchable; CCol TempCol; TESTC(pTable && pcParamColMap && rgParamColMap && pcDbParamBindInfo && rgDbParamBindInfo && rgParamOrdinals && rgTableInfo) //Make the parameter bindings for all searchable columns in //the table. for (ulIndex = 0; ulIndex < cColumnsOnTable; ulIndex++) { TESTC_(pTable->GetColInfo(ulIndex+1, TempCol), S_OK) ulSearchable = TempCol.GetSearchable() ; //SELECT_ALL_WITH_SEARCHABLE_AND_UPDATEABLE includes only //those columns in the command text which agree with the //following condition. if((ulSearchable == DB_LIKE_ONLY || ulSearchable == DB_ALL_EXCEPT_LIKE || ulSearchable == DB_SEARCHABLE ) && (TempCol.GetUpdateable()) && (!TempCol.GetIsLong()) ) { //Record the column number in the array if it is //searchable & updateable. rgParamColMap[*pcParamColMap] = (LONG_PTR) TempCol.GetColNum(); (*pcParamColMap)++; //Build Information for SetParameterInfo. rgParamOrdinals[*pcDbParamBindInfo] = *pcDbParamBindInfo + 1; rgDbParamBindInfo[*pcDbParamBindInfo].pwszDataSourceType = wcsDuplicate(TempCol.GetProviderTypeName()); rgDbParamBindInfo[*pcDbParamBindInfo].pwszName = NULL; rgDbParamBindInfo[*pcDbParamBindInfo].dwFlags = DBPARAMFLAGS_ISINPUT; if (TempCol.GetNullable()) rgDbParamBindInfo[*pcDbParamBindInfo].dwFlags |= DBPARAMFLAGS_ISNULLABLE; rgDbParamBindInfo[*pcDbParamBindInfo].ulParamSize = rgTableInfo[ulIndex].ulColumnSize; rgDbParamBindInfo[*pcDbParamBindInfo].bScale = (BYTE)rgTableInfo[ulIndex].bScale; rgDbParamBindInfo[*pcDbParamBindInfo].bPrecision = (BYTE)rgTableInfo[ulIndex].bPrecision; (*pcDbParamBindInfo)++; } } bSuccess = TRUE; CLEANUP: return bSuccess; } //MakeParamBindings //---------------------------------------------------------------------- //@mfunc Test GetParameterInfo for ICommandWithParameters. // TESTRESULT CQuickTest::testGetParamInfo( ICommandWithParameters* pICWP, CTable* pTable, DB_UPARAMS cDbParamBindInfo, DBPARAMBINDINFO* rgDbParamBindInfo, LONG_PTR* rgParamColMap ) { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr; DB_UPARAMS ulIndex; DB_UPARAMS cParams = 0; DBPARAMINFO* rgLocalParamInfo = NULL; WCHAR* pwszNamesBuffer = NULL; CCol TempCol; TESTC(pICWP && pTable && rgDbParamBindInfo && rgParamColMap) //Call GetParameterInfo. TESTC_(hr = pICWP->GetParameterInfo(&cParams, &rgLocalParamInfo, &pwszNamesBuffer), S_OK) TESTC(cParams == cDbParamBindInfo) TESTC(rgLocalParamInfo != NULL) //We did not give any names to the parameters when we called //SetParameterInfo. Hence, the names buffer should be NULL. if(pwszNamesBuffer != NULL) odtLog<GetColInfo(rgParamColMap[ulIndex], TempCol), S_OK) COMPAREW(rgLocalParamInfo[ulIndex].pTypeInfo, TempCol.GetTypeInfo()); if(rgLocalParamInfo[ulIndex].wType != TempCol.GetProviderType()) { odtLog<CreateCommand(NULL, IID_ICommand, (IUnknown**)&pICommand), S_OK) //Obtain pointer to ICommandWithParameters, if it is supported. if(!VerifyInterface(pICommand,IID_ICommandWithParameters, COMMAND_INTERFACE,(IUnknown**)&pICWP)) { odtLog<CreateTable(MIN_ROWS), S_OK) //Set command text to "select * from [table]" TESTC_(pTable->ExecuteCommand(SELECT_ALLFROMTBL, IID_IUnknown, NULL, NULL, NULL, NULL, EXECUTE_NEVER, 0, NULL, NULL, NULL, &pICommand), S_OK) //Prepare the command, if ICommandPrepare is supported. Preparing //the command is required for calling GetColumnInfo. if(pICommandPrepare) { TESTC_(pICommandPrepare->Prepare(1), S_OK) } //Get pointer to IColumnInfo. TESTC(VerifyInterface(pICommand,IID_IColumnsInfo, COMMAND_INTERFACE,(IUnknown**)&pIColumnsInfo)) //Get the column info (cmd text set to select all from table). TESTC_(pIColumnsInfo->GetColumnInfo(&cTableInfo, &rgTableInfo, &pTableStringsBuffer), S_OK); SAFE_RELEASE(pIColumnsInfo); cColumnsOnTable = pTable->CountColumnsOnTable(); SAFE_ALLOC(rgParamColMap, LONG_PTR, cColumnsOnTable) SAFE_ALLOC(rgParamOrdinals, DB_UPARAMS, cColumnsOnTable) SAFE_ALLOC(rgDbParamBindInfo, DBPARAMBINDINFO, cColumnsOnTable) memset(rgDbParamBindInfo, 0, (size_t) (cColumnsOnTable*sizeof(DBPARAMBINDINFO))); memset(rgParamColMap, 0, (size_t) (cColumnsOnTable*sizeof(LONG_PTR))); memset(rgParamOrdinals, 0, (size_t) (cColumnsOnTable*sizeof(DB_UPARAMS))); //Make the parameter bindings. TESTC(MakeParamBindings(pTable, cColumnsOnTable, &cParamColMap, rgParamColMap, &cDbParamBindInfo, rgDbParamBindInfo, rgParamOrdinals, rgTableInfo)) //Get the Bindings for the Searchable & Updateable columns by //passing an array containing the column ordinals for searchable //& updateable columns only. This is a command acessor. TESTC_(hr = GetAccessorAndBindings(pIAccessor, DBACCESSOR_PARAMETERDATA, &hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH, USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, cParamColMap, rgParamColMap, rgParamOrdinals, NO_COLS_OWNED_BY_PROV, DBPARAMIO_INPUT, BLOB_LONG ), S_OK) // Set the command text to a statement like "select col2,col5,... // from [table] where col2=?,col5=?,...". TESTC_(hr = pTable->ExecuteCommand( SELECT_ALL_WITH_SEARCHABLE_AND_UPDATEABLE, IID_IUnknown, NULL, &pwszSqlStmt, NULL, NULL, EXECUTE_NEVER, 0, NULL, NULL, NULL, &pICommand), S_OK) //Make sure the command text was built. TESTC(pwszSqlStmt != NULL) //Prepare the command. Required for GetParameterInfo. if(pICommandPrepare) { TESTC_(pICommandPrepare->Prepare(2), S_OK) } //GetParameterInfo will return DB_E_PARAMUNAVAILABLE if provider //cannot derive parameter information from the command. Otherwise, //it returns S_OK. TEST2C_(hrGetParam = pICWP->GetParameterInfo(&cParams, &rgLocalParamInfo, NULL), S_OK, DB_E_PARAMUNAVAILABLE) if (hrGetParam == DB_E_PARAMUNAVAILABLE) { TESTC(cParams==0 && rgLocalParamInfo==NULL) odtLog<SetParameterInfo(cDbParamBindInfo, rgParamOrdinals, rgDbParamBindInfo), S_OK, DB_S_TYPEINFOOVERRIDDEN) if(hrGetParam == DB_E_PARAMUNAVAILABLE) CHECK(hr, S_OK); if(hrGetParam == S_OK) CHECK(hr, DB_S_TYPEINFOOVERRIDDEN); //Make the parameter data (corresponding to row 1). TESTC_(hr = FillInputBindings(pTable, DBACCESSOR_PARAMETERDATA, cBindings, rgBindings, &pData, 1, cParamColMap, rgParamColMap), S_OK) //Set the DBPARAMS structure to contain the parameter data "pData". dbParams.pData = pData; dbParams.cParamSets = 1; dbParams.hAccessor = hAccessor; //Execute command with parameters. hr = pICommand->Execute(NULL, IID_IRowset, &dbParams, &cRowsAffected, (IUnknown**)&pIRowset) ; if(FAILED(hr)) { odtLog<GetData(rghRows[0], hAccessor, pData), S_OK) //The data has to match the data of the first row of base table. TESTC(CompareData(cParamColMap, rgParamColMap, 1, pData, cBindings, rgBindings, pTable, m_pIMalloc)) //Now test GetParameterInfo. TESTC(testGetParamInfo(pICWP, pTable, cDbParamBindInfo, rgDbParamBindInfo, rgParamColMap) == TEST_PASS) tTestResult = TEST_PASS; CLEANUP: CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ; for(ulIndex=0; ulIndexDropTable(); SAFE_DELETE(pTable); return tTestResult; } //testICmdWParam //--------------------------------------------------------------------- //@mfunc Make a sql select stmt with list of updateable columns. //Set the command text to this statement. //Execute command and request IMultipleResults. Get the first //rowset and verify. Release this rowset. Make sure there was only 1 //rowset in the results. // TESTRESULT CQuickTest::testIMultipleResults() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRows = 0; DBORDINAL cColumns = 0; DB_LORDINAL* rgColumnsOrd = NULL; DBROWCOUNT cRowsAffected = 0; WCHAR* pwszTableName = NULL; WCHAR* pwszSelectUpdt = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; DBBINDING* rgBindings = NULL; HACCESSOR hAccessor = DB_NULL_HACCESSOR; IAccessor* pIAccessor = NULL; IRowset* pIRowset1 = NULL; IRowset* pIRowset2 = NULL; ICommandText* pICmdText = NULL; IMultipleResults* pIMR = NULL; //Create a command object. TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText, (IUnknown**)&pICmdText), S_OK) TESTC(m_pTable != NULL) pwszTableName = m_pTable->GetTableName(); //Get number of rows. cRows = m_pTable->CountRowsOnTable(); //Make a sql select stmt with list of updateable columns. TESTC_(hr = m_pTable->CreateSQLStmt(SELECT_UPDATEABLE, pwszTableName, &pwszSelectUpdt, &cColumns, &rgColumnsOrd), S_OK) TESTC(pwszSelectUpdt != NULL) //Set the command text to the multiple stmt. TESTC_(hr = pICmdText->SetCommandText(DBGUID_DEFAULT, pwszSelectUpdt), S_OK) //Execute command and request IMultipltResults. TESTC_(hr = pICmdText->Execute(NULL, IID_IMultipleResults, NULL, &cRowsAffected, (IUnknown**)&pIMR), S_OK) //Get the first rowset and verify. cRowsAffected is undefined //on output. TESTC_(hr = pIMR->GetResult(NULL, 0, IID_IRowset, &cRowsAffected, (IUnknown**)&pIRowset1), S_OK) TESTC(VerifyInterface(pIRowset1,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) TESTC_(hr=GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Make sure we are on the first row. TESTC_(RestartPosition(pIRowset1), S_OK) //For each row in the table, fetch the row, compare the data in the //row and release the row. for(ulIndex=0; ulIndexReleaseAccessor(hAccessor, NULL), S_OK); hAccessor = DB_NULL_HACCESSOR; SAFE_RELEASE(pIAccessor); SAFE_RELEASE(pIRowset1); //Calling GetResult a second time should return DB_S_NORESULT, //as there was only 1 sql stmt in the command text. TESTC_(hr = pIMR->GetResult(NULL, 0, IID_IRowset, &cRowsAffected, (IUnknown**)&pIRowset2), DB_S_NORESULT) TESTC(pIRowset2 == NULL) tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(pwszSelectUpdt); PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowset1); SAFE_RELEASE(pIRowset2); SAFE_RELEASE(pIMR); SAFE_RELEASE(pICmdText); return tTestResult; } //testIMultipleResults //---------------------------------------------------------------------- //@mfunc Check if IDBCreateSession has error support. Call CreateSession //with an invalid argument. Get the error records and get an IErrorInfo //for every record. Loop through each record and verify the various //information returned by the methods of IErrorInfo. // TESTRESULT CQuickTest::testIError() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG ulIndex = 0; LCID lcid ; GUID guid ; DWORD dwHelpContext = 0; ULONG cRecords = 0; BSTR bstrDescription; BSTR bstrHelpFile; BSTR bstrSource ; WCHAR* wszString = NULL ; IErrorInfo** rgIErrorInfo = NULL; IErrorInfo* pIEI = NULL; IErrorRecords* pIER = NULL; IErrorLookup* pIEL = NULL; ISupportErrorInfo* pISEI = NULL; IDBCreateSession* pIDBCS = NULL; //Get ISupportErrorInfo. if (!VerifyInterface(m_pIDBInitialize, IID_ISupportErrorInfo, DATASOURCE_INTERFACE, (IUnknown **)&pISEI)) { odtLog << L"Interface ISupportErrorInfo is not supported.\n"; return TEST_SKIPPED; } //Check if IDBCreateSession has error support. hr = pISEI->InterfaceSupportsErrorInfo(IID_IDBCreateSession); if (hr == S_FALSE) { SAFE_RELEASE(pISEI); odtLog<CreateSession(NULL, IID_IOpenRowset, NULL); TESTC_(hr, E_INVALIDARG) //Validate the correct behavior for the given error situation. TESTC(XCHECK((IUnknown*)pIDBCS, IID_IDBCreateSession, hr)) hr = pIDBCS->CreateSession(NULL, IID_IOpenRowset, NULL); TESTC_(hr, E_INVALIDARG) //Get the IErrorInfo interface. hr = GetErrorInfo(0, &pIEI) ; if(hr == S_FALSE) { odtLog<GetRecordCount(&cRecords), S_OK)) goto CLEANUP; //There has to be at least one error record. if (cRecords == 0) { odtLog << L"No error records were found in the error object.\n"; goto CLEANUP; } //Now get an IErrorInfo for every record rgIErrorInfo = (IErrorInfo **)PROVIDER_ALLOC(sizeof(IErrorInfo *) * cRecords); TESTC(rgIErrorInfo != NULL) lcid = GetSystemDefaultLCID(); //For each record... for (ulIndex=0; ulIndexGetErrorInfo(ulIndex, lcid, (IErrorInfo**)&rgIErrorInfo[ulIndex]), S_OK) } //Loop through each error record. for (ulIndex = cRecords; ulIndex > 0; ulIndex--) { //GetDescription. if(CHECK(hr = ((IErrorInfo *)rgIErrorInfo[ulIndex-1])->GetDescription( &bstrDescription), S_OK)) { if (wszString = BSTR2WSTR(bstrDescription, TRUE)) { TESTC(wcslen(wszString) > 0) odtLog << L"INFO: Description for record " << ulIndex-1 << L":" << wszString << L"\n" ; PROVIDER_FREE(wszString); } } //GetGUID. if(CHECK(hr = ((IErrorInfo *)rgIErrorInfo[ulIndex-1])->GetGUID( &guid), S_OK)) { //Make sure the right interface was returned TESTC(guid == IID_IDBCreateSession) } //GetHelpContext CHECK(hr = ((IErrorInfo *)rgIErrorInfo[ulIndex-1])->GetHelpContext( &dwHelpContext), S_OK) ; //GetHelpFile if(CHECK(hr = ((IErrorInfo *)rgIErrorInfo[ulIndex-1])->GetHelpFile( &bstrHelpFile), S_OK)) { if (wszString = BSTR2WSTR(bstrHelpFile, TRUE)) { odtLog << L"INFO: Help File for record " << ulIndex-1 << L":" << wszString << L"\n"; odtLog << L"INFO: Help Context = "<GetSource( &bstrSource), S_OK)) { if (wszString = BSTR2WSTR(bstrSource, TRUE)) { TESTC(wcslen(wszString) > 0) odtLog << L"INFO: Source for record " << ulIndex-1 << L":" << wszString << L"\n"; PROVIDER_FREE(wszString); } } } //For-Loop Ends. tTestResult = TEST_PASS; CLEANUP: if (rgIErrorInfo) { //Release each records IErrorInfo interface for (ulIndex=0; ulIndexStartTransaction(ISOLATIONLEVEL_READCOMMITTED, 0, NULL, &ulTransLevel), S_OK) //Open a rowset with above properties set. TEST2C_(hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**) &pIRowset), S_OK, DB_S_ERRORSOCCURRED) //Get value of the DBPROP_UPDATABILITY property. if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*) pIRowset, &updtFlag)) { odtLog<GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) TESTC(VerifyInterface(pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) if(bProvUpdateable) { TESTC(VerifyInterface(pIRowset,IID_IRowsetChange, ROWSET_INTERFACE,(IUnknown**)&pIRowsetChange)) } //Create Accessor with a binding using length, status and value. //This accessor binds the updateable non-index columns. TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Get the value of the property DBPROP_COMMITPRESERVE. if(GetProperty(DBPROP_COMMITPRESERVE, DBPROPSET_ROWSET, (IUnknown*) pIRowset)) bCommitPreserve = TRUE; //Allocate a new data buffer SAFE_ALLOC(pData, BYTE, cbRowSize) memset(pData, 0, (size_t) cbRowSize); //Restart position. TESTC_(RestartPosition(pIRowset), S_OK) //Get third row. TESTC_(hr = GetNextRows(pIRowset, NULL,2,1,&cRowsObtained, &rghRows),S_OK) //Make data corresponding to row (g_ulNextRow+1). TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA, cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols, rgColumnsOrd, PRIMARY),S_OK) if(bProvUpdateable) { //Set data corresponding to row (g_ulNextRow+1). TESTC_(hr = pIRowsetChange->SetData(rghRows[0],hAccessor, pData),S_OK) } //Release...cleanup... CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ; pData = NULL; FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetChange); //pIRowset has not been freed. //Commit the transaction with fRetaining=FALSE. //FUTURE ATTENTION required here. if((hr=pITL->Commit(FALSE, XACTTC_SYNC, 0)) == XACT_E_NOTSUPPORTED) if((hr=pITL->Commit(FALSE, XACTTC_SYNC_PHASETWO, 0)) == XACT_E_NOTSUPPORTED) if((hr=pITL->Commit(FALSE, XACTTC_ASYNC_PHASEONE, 0)) == XACT_E_NOTSUPPORTED) if((hr=pITL->Commit(FALSE, XACTTC_SYNC_PHASEONE, 0)) == XACT_E_NOTSUPPORTED) if((hr=pITL->Commit(FALSE, 0, 0)) == XACT_E_NOTSUPPORTED) { odtLog<GetData(rghRows[0], hAccessor, pData), S_OK) if(bProvUpdateable) { //The first row should contain the new data which was set in //the transaction before committing. TESTC(CompareData(cRowsetCols, rgColumnsOrd, g_ulNextRow, pData, cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY, COMPARE_ONLY)) } tTestResult = TEST_PASS; CLEANUP: CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); if(pData) ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ; PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetChange); SAFE_RELEASE(pIRowset); if((hr=pITL->Abort(NULL, FALSE, FALSE)) == XACT_E_NOTSUPPORTED) hr=pITL->Abort(NULL, FALSE, TRUE) ; SAFE_RELEASE(pITL); return tTestResult; } //testTransactionCommit //---------------------------------------------------------------------- //@mfunc Start a transaction. Open a rowset with updateable properties. //Get the third row and set its data to some new data. Now abort the //transaction (fPreserve=FALSE). If DBPROP_ABORTPRESERVE is FALSE, then //release the rowset and open another rowset. Verify that the third row //has the old data. // TESTRESULT CQuickTest::testTransactionAbort() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; ULONG_PTR updtFlag = 0; BOOL bProvUpdateable = TRUE; BOOL bAbortPreserve = FALSE; ULONG ulTransLevel = 0; DBCOUNTITEM cRowsObtained = 0; DBORDINAL cRowsetCols = 0; DB_LORDINAL* rgColumnsOrd = NULL; HROW* rghRows = NULL; BYTE* pData = NULL; BYTE* pOrgData = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; IRowset* pIRowset = NULL; IAccessor* pIAccessor = NULL; IRowsetChange* pIRowsetChange = NULL; ITransactionLocal* pITL = NULL; //Get ITransactionLocal. if(!VerifyInterface(m_pIOpenRowset, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown **)&pITL)) { odtLog << L"ITransactionLocal is not supported.\n"; return TEST_SKIPPED; } FreeProperties(&m_cPropSets, &m_rgPropSets); LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE| DBPROPVAL_UP_DELETE| DBPROPVAL_UP_INSERT ; //Set the following properties. SetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetSettableProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; //Start a transaction. TESTC_(hr = pITL->StartTransaction(ISOLATIONLEVEL_READCOMMITTED, 0, NULL, &ulTransLevel), S_OK) //Open a rowset with above properties set. TEST2C_(hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**) &pIRowset), S_OK, DB_S_ERRORSOCCURRED) //Get value of the DBPROP_UPDATABILITY property. if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*) pIRowset, &updtFlag)) { odtLog<GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) TESTC(VerifyInterface(pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) if(bProvUpdateable) { TESTC(VerifyInterface(pIRowset,IID_IRowsetChange, ROWSET_INTERFACE,(IUnknown**)&pIRowsetChange)) } //Create Accessor with a binding using length, status and value. //This accessor binds the updateable non-index columns. TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS, NULL),S_OK) //Get the value of the property DBPROP_ABORTPRESERVE. if(GetProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET, (IUnknown*) pIRowset)) bAbortPreserve = TRUE; //Allocate a new data buffer SAFE_ALLOC(pOrgData, BYTE, cbRowSize) memset(pOrgData, 0, (size_t) cbRowSize); //Restart position. TESTC_(RestartPosition(pIRowset), S_OK) //Get third row. TESTC_(hr = GetNextRows(pIRowset, NULL,2,1,&cRowsObtained, &rghRows),S_OK) TESTC_(hr = pIRowset->GetData(rghRows[0], hAccessor, pOrgData), S_OK) //Make data corresponding to row (g_ulNextRow+1). TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA, cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols, rgColumnsOrd, PRIMARY),S_OK) if(bProvUpdateable) { //Set data corresponding to row (g_ulNextRow+1). TESTC_(hr = pIRowsetChange->SetData(rghRows[0],hAccessor, pData),S_OK) } //Release...cleanup... CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ; pData = NULL; FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetChange); //Abort the transaction with fRetaining=FALSE. if((hr=pITL->Abort(NULL, FALSE, FALSE)) == XACT_E_NOTSUPPORTED) if((hr=pITL->Abort(NULL, FALSE, TRUE)) == XACT_E_NOTSUPPORTED) { odtLog<GetData(rghRows[0], hAccessor, pData), S_OK) //The data should correspond to the original data of first row. TESTC(CompareBuffer(pOrgData,pData,cBindings,rgBindings, m_pIMalloc,TRUE, FALSE, COMPARE_ONLY)) tTestResult = TEST_PASS; CLEANUP: CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); if(pData) ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ; if(pOrgData) ReleaseInputBindingsMemory(cBindings, rgBindings,pOrgData, TRUE); PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pIRowsetChange); SAFE_RELEASE(pIRowset); if((hr=pITL->Abort(NULL, FALSE, FALSE)) == XACT_E_NOTSUPPORTED) hr=pITL->Abort(NULL, FALSE, TRUE) ; SAFE_RELEASE(pITL); return tTestResult; } //testTransactionAbort //---------------------------------------------------------------------- //@mfunc Create an accessor binding all columns. Look for a binding of //type DBTYPE_IUNKNOWN. Fetch the first row and get its data. Compare //the data for the DBTYPE_IUNKNOWN binding. CompareData gets the //ISequentialStream interface and calls read. It then verifies the data //read through ISequentialStream. // TESTRESULT CQuickTest::testStorageObj() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBCOUNTITEM ulBinding = 0; DBCOUNTITEM cRowsObtained = 0; DBORDINAL cRowsetCols = 0; DB_LORDINAL* rgColumnsOrd = NULL; HROW* rghRows = NULL; BYTE* pData = NULL; DBLENGTH cbRowSize = 0; DBCOUNTITEM cBindings = 0; HACCESSOR hAccessor = DB_NULL_HACCESSOR; DBBINDING* rgBindings = NULL; IRowset* pIRowset = NULL; IAccessor* pIAccessor = NULL; ISequentialStream* pISS = NULL; FreeProperties(&m_cPropSets, &m_rgPropSets); //Set the following properties. IRowsetLocate is required if //we have bound BLOB columns and are going to fetch the data. SetSupportedProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; //Open a rowset with above properties set. hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)&pIRowset); if(hr == DB_E_ERRORSOCCURRED) { TESTC(!pIRowset) DumpPropertyErrors(m_cPropSets, m_rgPropSets); FreeProperties(&m_cPropSets, &m_rgPropSets); TESTC(!pIRowset) return TEST_SKIPPED; } TESTC_(hr, S_OK) //Get list of ordinals. TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols, &rgColumnsOrd, NULL, NULL, NULL, NULL)) TESTC(VerifyInterface(pIRowset,IID_IAccessor, ROWSET_INTERFACE,(IUnknown**)&pIAccessor)) //Create Accessor with a binding using length, status and value. //This accessor binds all columns. Include BLOB_IID_ISEQSTREAM //and BLOB_BIND_STR. TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,&hAccessor, &rgBindings, &cBindings, &cbRowSize, DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE, ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_IID_ISEQSTREAM|BLOB_BIND_STR, NULL),S_OK) //There should be a binding of type DBTYPE_IUNKNOWN for this test. if(!FindBinding(cBindings, rgBindings, DBTYPE_IUNKNOWN, &ulBinding)) { odtLog<GetData(rghRows[0], hAccessor, pData), S_OK) TESTC_(hr = GetStorageData(cBindings, rgBindings, pData, NULL, NULL, IID_ISequentialStream, (IUnknown**)&pISS), S_OK) TESTC(pISS != NULL) //Compare the data for the DBTYPE_IUNKNOWN binding. This function //gets the ISequentialStream interface and calls read. It then //verifies the data read through ISequentialStream. TESTC(CompareData(cRowsetCols, rgColumnsOrd, 1, pData, 1, &rgBindings[ulBinding], m_pTable, m_pIMalloc, PRIMARY, COMPARE_ONLY)) tTestResult = TEST_PASS; CLEANUP: CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK); if(pData) ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ; FreeProperties(&m_cPropSets, &m_rgPropSets); PROVIDER_FREE(rgColumnsOrd); FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings); SAFE_RELEASE(pISS); SAFE_RELEASE(pIRowset); return tTestResult; } //testStorageObj //---------------------------------------------------------------------- // Test the IRow interface of the row object. // BOOL CQuickTest::testIRow(IRow* pIRow, DBCOUNTITEM ulRowNum) { TBEGIN HRESULT hr = E_FAIL; CRowObject CRow; IRowset* pIRowset = NULL; IAccessor* pIAccessor = NULL; if(!pIRow || !m_pTable) return FALSE; //Try to get the source rowset of this row object. TEST2C_(hr=pIRow->GetSourceRowset(IID_IRowset, (IUnknown**)&pIRowset, NULL), S_OK, DB_E_NOSOURCEOBJECT) //Try to get the source rowset again, with a different iid. if(hr==S_OK) TESTC_(hr=pIRow->GetSourceRowset(IID_IAccessor, (IUnknown**)&pIAccessor, NULL), S_OK) else TESTC_(hr=pIRow->GetSourceRowset(IID_IAccessor, (IUnknown**)&pIAccessor, NULL), DB_E_NOSOURCEOBJECT) if(hr==S_OK) TESTC((pIAccessor != NULL) && (pIRowset!= NULL)) else odtLog<pIRow())) if(bTestResColInfo) TESTC(VerifyInterface(pCRowObj->pIRow(), IID_IColumnsInfo2, ROW_INTERFACE, (IUnknown**)&pICI2)) else TESTC(VerifyInterface(pCRowObj->pIRow(), IID_IColumnsInfo, ROW_INTERFACE, (IUnknown**)&pICI)) //Test GetColumnInfo method. if(pICI2) TESTC_(pICI2->GetColumnInfo(&ulCols, &rgColInfo, &pStrBuf), S_OK) else TESTC_(pICI->GetColumnInfo(&ulCols, &rgColInfo, &pStrBuf), S_OK) TESTC(ulCols!=0 && rgColInfo!=NULL && pStrBuf!=NULL) //Verify the number of columns. if(rgColInfo[0].iOrdinal==0) TESTC(ulCols-1 >= m_pTable->CountColumnsOnTable()) else TESTC(ulCols >= m_pTable->CountColumnsOnTable()) //Verify the DBCOLUMNINFO values. for(ulIndex=0; ulIndexGetColInfo(rgColInfo[ulIndex].iOrdinal, rgCol) != S_OK) continue; cColsInBaseTable++; //Verify the column name. if((rgColInfo[ulIndex].pwszName)&&(rgCol.GetColName())) TESTC(wcscmp(rgColInfo[ulIndex].pwszName, rgCol.GetColName()) == 0) else TESTC((rgColInfo[ulIndex].pwszName == NULL)&& (rgCol.GetColName() == NULL)) //ITypeInfo is reserved for future use. TESTC(rgColInfo[ulIndex].pTypeInfo == rgCol.GetTypeInfo()) //Verify the DBTYPE. TESTC(rgColInfo[ulIndex].wType == rgCol.GetProviderType()) //Compare the column IDs. if(!CompareDBID(rgColInfo[ulIndex].columnid, *(rgCol.GetColID()))) { if(ulIndex>1) TESTC(fColIDWarning) TESTC(rgColInfo[ulIndex].columnid.eKind != (*(rgCol.GetColID())).eKind) fColIDWarning = TRUE; } } TESTC(cColsInBaseTable == m_pTable->CountColumnsOnTable()) if(fColIDWarning) { //Issue a warning. odtLog<GetRestrictedColumnInfo(0, INVALID(DBID*), 0, &ulCols2, &rgColIDs, &rgColInfo2, &pStrBuf2), S_OK) //The columns obtained from GetRestrictedColumnInfo with zero //restrictions has to be same as that obtained from GetColumnInfo method. TESTC(ulCols2 == ulCols) TESTC(rgColIDs!=NULL && rgColInfo2!=NULL && pStrBuf2!=NULL) for(ulIndex=0; ulIndexGetRestrictedColumnInfo(4, rgColIDMasks, 0, &ulCols2, &rgColIDs, &rgColInfo2, &pStrBuf2), S_OK, DB_E_NOCOLUMN) if(hr==S_OK) TESTC(ulCols2>0 && rgColIDs!=NULL && rgColInfo2!=NULL && pStrBuf2!=NULL) else TESTC(ulCols2==0 && rgColIDs==NULL && rgColInfo2==NULL && pStrBuf2==NULL) for(ulIndex=0; ulIndexCreateColAccess(&cColAccess, &rgColAccess, &pData, &cbRowSize, UPDATEABLE_NONINDEX_COLS_BOUND), S_OK) TESTC_(pCRowObj->FillColAccess(m_pTable, cColAccess, rgColAccess, 2, PRIMARY), S_OK) //Call SetColumns to change the data in the row object. TESTC_(pCRowObj->SetColumns(cColAccess, rgColAccess), S_OK) //Verify new data in row object. TESTC(pCRowObj->VerifyGetColumns(2, m_pTable, UPDATEABLE_NONINDEX_COLS_BOUND)) //Replace the original data by calling SetColumns again. TESTC_(pCRowObj->FillColAccess(m_pTable, cColAccess, rgColAccess, 1, PRIMARY), S_OK) TESTC_(pCRowObj->SetColumns(cColAccess, rgColAccess), S_OK) TESTC(pCRowObj->VerifyGetColumns(1, m_pTable, UPDATEABLE_NONINDEX_COLS_BOUND)) CLEANUP: FreeColAccess(cColAccess, rgColAccess); SAFE_FREE(pData); TRETURN } //testIRowChange //---------------------------------------------------------------------- // @mfunc Test the IRowSchemaChange interface. // BOOL CQuickTest::testIRowSchemaChange(CRowObject* pCRowObj) { TBEGIN DBORDINAL ulIndex = 0; DBLENGTH cbRowSize = 0; DBORDINAL cColAccess = 0; DBCOLUMNACCESS* rgColAccess = NULL; DBCOLUMNINFO* rgNewColInfo = NULL; void* pData = NULL; DBORDINAL cColInfo2 = 0; DBORDINAL cColInfo = 0; DBCOLUMNINFO* rgColInfo = NULL; WCHAR* pwszBuff = NULL; DBSTATUS dwStatus = 0; IColumnsInfo* pICI = NULL; IRowSchemaChange* pIRSC = NULL; TESTC((pCRowObj!=NULL) && (m_pTable!=NULL)) //Create the DBCOLUMNACCESS struct and fill in data. One //column from this will be modified and used for AddColumn. TESTC_(pCRowObj->CreateColAccess(&cColAccess, &rgColAccess, &pData, &cbRowSize, UPDATEABLE_NONINDEX_COLS_BOUND), S_OK) TESTC_(pCRowObj->FillColAccess(m_pTable, cColAccess, rgColAccess, 2, PRIMARY), S_OK) //Allocate a new DBCOLUMNINFO struct to pass in to AddColumns. SAFE_ALLOC(rgNewColInfo, DBCOLUMNINFO, 1); memset(rgNewColInfo, 0, sizeof(DBCOLUMNINFO)); TESTC(VerifyInterface(pCRowObj->pIRow(), IID_IColumnsInfo, ROW_INTERFACE, (IUnknown**)&pICI)) TESTC_(pICI->GetColumnInfo(&cColInfo, &rgColInfo, &pwszBuff), S_OK) //Get the column info for same column as in rgColAccess[0]. for(ulIndex=0; ulIndexpIRow(), IID_IRowSchemaChange, ROW_INTERFACE, (IUnknown**)&pIRSC)) //Add the new column. TESTC_(pIRSC->AddColumns(1, rgNewColInfo, rgColAccess), S_OK) TESTC(rgColAccess[0].dwStatus == DBSTATUS_S_OK) SAFE_FREE(rgColInfo); //Verify the new column was added. TESTC_(pICI->GetColumnInfo(&cColInfo2, &rgColInfo, &pwszBuff), S_OK) TESTC(cColInfo2 = cColInfo+1) for(ulIndex=0; ulIndexDeleteColumns(1, &rgNewColInfo[0].columnid, &dwStatus), S_OK) TESTC(dwStatus == DBSTATUS_S_OK) //Verify the new column is deleted. TESTC_(pICI->GetColumnInfo(&cColInfo2, &rgColInfo, &pwszBuff), S_OK) TESTC(cColInfo2 = cColInfo) for(ulIndex=0; ulIndexCreateSession(NULL, IID_IOpenRowset, (IUnknown**)&pIOpenRowset), S_OK)) goto CLEANUP; if(hr == S_OK) tTestResult = TEST_PASS; CLEANUP: //Release Session. SAFE_RELEASE(pIOpenRowset); SAFE_RELEASE(pIDBCreateSession); //Release the DSO. SAFE_RELEASE(pIDBInitialize); return tTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*--------------------------------------------------------------------- // @mfunc IDBInitialize::Uninitialize //and then calls Uninitialize on it. // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_2() { IDBInitialize* pIDBInitialize = NULL; IDBProperties* pIDBProperties = NULL; ULONG cPropSets =0; DBPROPSET* rgPropSets = NULL; TESTRESULT tTestResult = TEST_FAIL; HRESULT hr; //Create a new DSO. CHECK(hr = GetModInfo()->CreateProvider(NULL, IID_IDBInitialize, (IUnknown**)&pIDBInitialize), S_OK); if(pIDBInitialize==NULL) { odtLog<SetProperties(cPropSets, rgPropSets), S_OK); //Calling Uninitialize before Initialize should succeed. CHECK(hr = pIDBInitialize->Uninitialize(), S_OK); if(hr != S_OK) { odtLog<Initialize(), S_OK); if(hr != S_OK) { odtLog<Uninitialize(), S_OK); if(hr == S_OK) tTestResult = TEST_PASS; CLEANUP: FreeProperties(&cPropSets, &rgPropSets); //Release the DSO. SAFE_RELEASE(pIDBProperties); SAFE_RELEASE(pIDBInitialize); return tTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*--------------------------------------------------------------------- // @mfunc IDBCreateSession // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_3() { TESTRESULT tTestResult = TEST_FAIL; IDBCreateSession* pIDBCreateSession = NULL; IOpenRowset* pIOpenRowset = NULL; //Make sure that DSO is initialized before creating session. if(!m_fInitialized) CHECK(InitializeDSO(REINITIALIZE_NO), S_OK) ; if(!VerifyInterface(m_pIDBInitialize, IID_IDBCreateSession, DATASOURCE_INTERFACE,(IUnknown**) &pIDBCreateSession)) { odtLog<CreateSession(NULL, IID_IOpenRowset, (IUnknown**)&pIOpenRowset), S_OK) TESTC(pIOpenRowset != NULL) tTestResult = TEST_PASS; CLEANUP: SAFE_RELEASE(pIOpenRowset) ; SAFE_RELEASE(pIDBCreateSession) ; return tTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*--------------------------------------------------------------------- // @mfunc IDBProperties::GetProperties // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_4() { return testGetProperties() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(5) //*--------------------------------------------------------------------- // @mfunc IDBProperties::GetProperties(ALL) // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_5() { return testGetAllProperties(m_pIDBProperties) ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(6) //*--------------------------------------------------------------------- // @mfunc IDBProperties::GetPropertyInfo // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_6() { return testGetPropInfo() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(7) //*--------------------------------------------------------------------- // @mfunc IDBProperties::GetPropertyInfo(ALL) // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_7() { return testGetAllPropInfo(m_pIDBProperties) ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(8) //*--------------------------------------------------------------------- // @mfunc IDBProperties::SetProperties // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_8() { return ((testSetProperties1() == TEST_PASS) && (testSetProperties2() == TEST_PASS)) ? TEST_PASS : TEST_FAIL; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(9) //*--------------------------------------------------------------------- // @mfunc Get properties before initialization // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_9() { return testGetPropBeforeInit() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc IDBInfo::GetKeywords // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_10() { return testGetKeywords(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc IDBInfo::GetLiteralInfo // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_11() { return testGetLiteralInfo(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc ISourcesRowset // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_12() { return testISrcRowset(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc IDataInitialize::CreateDBInstance // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_13() { return testIDataIzCreateDBIns(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc IDataInitialize::GetDataSource // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_14() { return testIDataIzGetDS(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(15) //*--------------------------------------------------------------------- // @mfunc IPersist::GetClassID // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_15() { CLSID clsid; IPersist * pIPersist; //Return if this interface is not supported if (!VerifyInterface(m_pIDBInitialize,IID_IPersist, DATASOURCE_INTERFACE,(IUnknown **)&pIPersist)) return TEST_FAIL; //Verify that CLSID returned is identical to the Provider CLSID CHECK(pIPersist->GetClassID(&clsid), S_OK); SAFE_RELEASE(pIPersist); return (clsid == GetModInfo()->GetThisTestModule()->m_ProviderClsid) ? TEST_PASS : TEST_FAIL; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(16) //*--------------------------------------------------------------------- // @mfunc IPersistFile::GetClassID // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_16() { CLSID clsid; //Return if this interface is not supported if(m_pIPersistFile == NULL) return TEST_SKIPPED; //Verify that CLSID returned is identical to the Provider CLSID CHECK(m_pIPersistFile->GetClassID(&clsid), S_OK); return (clsid == GetModInfo()->GetThisTestModule()->m_ProviderClsid) ? TEST_PASS : TEST_FAIL; } // }} // {{ TCW_VAR_PROTOTYPE(17) //*--------------------------------------------------------------------- // @mfunc IPersistFile::IsDirty // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_17() { if(m_pIPersistFile == NULL) return TEST_SKIPPED; //We haven't called Save yet, so we should be in a dirty state. //S_FALSE is only returned when the object had been saved and has //maintained the same state since. CHECK(m_hr = m_pIPersistFile->IsDirty(),S_OK); return (m_hr == S_OK) ? TEST_PASS : TEST_FAIL; } // }} // {{ TCW_VAR_PROTOTYPE(18) //*--------------------------------------------------------------------- // @mfunc IPersistFile::Save // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_18() { if(m_pIPersistFile == NULL) return TEST_SKIPPED; //Test if the save to file succeeds. m_hr = PersistToFile(); if (m_hr ==S_OK) { //If SAVE was successful, then the IsDirty should be FALSE. CHECK(m_pIPersistFile->IsDirty(),S_FALSE); return TEST_PASS; } else if (m_hr == E_NOTIMPL) { COMPARE((GetModInfo()->UseServiceComponents() & SERVICECOMP_INVOKE), SERVICECOMP_INVOKE); return TEST_SKIPPED; } return TEST_FAIL; } // }} // {{ TCW_VAR_PROTOTYPE(19) //*--------------------------------------------------------------------- // @mfunc IPersistFile::SaveCompleted // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_19() { BOOL fResults = FALSE; if(m_pIPersistFile == NULL) return TEST_SKIPPED; //Do the save m_hr = PersistToFile(); if (m_hr == S_OK) { //Save completed should now return S_OK if (CHECK(m_pIPersistFile->SaveCompleted(m_wszFile),S_OK)) fResults = TRUE; return (fResults) ? TEST_PASS : TEST_FAIL; } else if (m_hr == E_NOTIMPL) { COMPARE((GetModInfo()->UseServiceComponents() & SERVICECOMP_INVOKE), SERVICECOMP_INVOKE); return TEST_SKIPPED; } return TEST_FAIL; } // }} // {{ TCW_VAR_PROTOTYPE(20) //*--------------------------------------------------------------------- // @mfunc IPersistFile::Load // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_20() { BOOL fResults = FALSE; if(m_pIPersistFile == NULL) return TEST_SKIPPED; //Do the save m_hr = PersistToFile(); if (m_hr == S_OK) { //We must release the current session for uninitialize to work if(m_pIOpenRowset != NULL || m_pIDBCreateCommand != NULL) ReleaseDBSession(); //Uninitialize. if (CHECK(UninitializeDSO(), S_OK)) { //Now Load should succeed if (CHECK(m_pIPersistFile->Load((LPOLESTR)m_wszFile, STGM_READWRITE),S_OK)) { // Initialize the Provider with Loaded Properties if (CHECK(InitializeDSO(), S_OK)) fResults = TRUE; } } return (fResults) ? TEST_PASS : TEST_FAIL; } else if (m_hr == E_NOTIMPL) { COMPARE((GetModInfo()->UseServiceComponents() & SERVICECOMP_INVOKE), SERVICECOMP_INVOKE); return TEST_SKIPPED; } return TEST_FAIL; } // }} // {{ TCW_VAR_PROTOTYPE(21) //*--------------------------------------------------------------------- // @mfunc IPersistFile::GetCurFile // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_21() { LPOLESTR pwszCurFile = NULL; BOOL fResults = FALSE; if(m_pIPersistFile == NULL) return TEST_SKIPPED; //Do the save m_hr = PersistToFile(); if (m_hr == S_OK) { if(!CHECK(m_pIPersistFile->GetCurFile(&pwszCurFile),S_OK)) return TEST_FAIL; //If any of these is NULL, fail test. if(pwszCurFile && m_wszFile) { //Returns 0 when identical fResults = COMPARE(wcscmp(pwszCurFile,m_wszFile),0); } PROVIDER_FREE(pwszCurFile); return (fResults) ? TEST_PASS : TEST_FAIL; } else if (m_hr == E_NOTIMPL) { COMPARE((GetModInfo()->UseServiceComponents() & SERVICECOMP_INVOKE), SERVICECOMP_INVOKE); return TEST_SKIPPED; } return TEST_FAIL; } // }} // {{ TCW_TERMINATE_METHOD //---------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCDataSource::Terminate() { CHAR* pszFile = NULL; //Delete file we used for persistence if (m_wszFile[0] != L'\0') { pszFile = ConvertToMBCS(m_wszFile); remove(pszFile); } PROVIDER_FREE(pszFile); FreeProperties(&m_cPropInfoSets, &m_rgPropInfoSets); FreeProperties(&m_cPropIDSets, &m_rgPropIDSets); SAFE_RELEASE(m_pIPersistFile); SAFE_RELEASE(m_pIDBProperties); ReleaseDBSession(); ReleaseDataSourceObject(); // {{ TCW_TERM_BASECLASS_CHECK2 return(CQuickTest::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCSession) //*--------------------------------------------------------------------- //| Test Case: TCSession - Session Interfaces //| Created: 3/18/98 //*--------------------------------------------------------------------- //*--------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCSession::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CQuickTest::Init()) // }} { if(CHECK(m_hr = CreateDBSession(),S_OK)) { CTable* pTable = NULL; //Required for using some ExtraLib functions. g_pIDBInitialize = m_pIDBInitialize; g_pIOpenRowset = m_pIOpenRowset; //Create a table with MIN_ROWS rows. if(CreateTable(&pTable, MIN_ROWS)) { SetTable(pTable, DELETETABLE_NO); if(m_pTable) return TRUE; } } } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*--------------------------------------------------------------------- // @mfunc IGetDataSource // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_1() { return testGetDataSource() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*--------------------------------------------------------------------- // @mfunc IOpenRowset // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_2() { return testOpenRowset() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*--------------------------------------------------------------------- // @mfunc ISessionProperties::GetProperties // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_3() { return testSessGetProp() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*--------------------------------------------------------------------- // @mfunc ISessionProperties::SetProperties // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_4() { return testSessSetProp() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc IDBCreateCommand // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_5() { if(!m_pIDBCreateCommand) { odtLog<DropTable(); SAFE_DELETE(m_pTable); ReleaseDBSession(); ReleaseDataSourceObject(); // {{ TCW_TERM_BASECLASS_CHECK2 return(CQuickTest::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCRowsetNotUpdateable) //*--------------------------------------------------------------------- //| Test Case: TCRowsetNotUpdateable - Rowset Interfaces (Non-Updateable Rowset) //| Created: 3/24/98 //*--------------------------------------------------------------------- //*--------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCRowsetNotUpdateable::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CQuickTest::Init()) // }} { if(CHECK(m_hr = CreateDBSession(),S_OK)) { CTable* pTable = NULL; //Required for using some ExtraLib functions without using //the ExtraLib classes. g_pIDBInitialize = m_pIDBInitialize; g_pIOpenRowset = m_pIOpenRowset; //Create a table with MIN_ROWS rows. if(CreateTable(&pTable, MIN_ROWS)) { SetTable(pTable, DELETETABLE_NO); //Set the following properties. SetProperty(DBPROP_IRowsetScroll, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_IRowsetFind, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_IColumnsRowset, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_ORDEREDBOOKMARKS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_CANSCROLLBACKWARDS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; //Open a rowset with above properties set. m_hr=CreateOpenRowset(m_pTable, IID_IRowset, (IUnknown**)&m_pIRowset); if(FAILED(m_hr)) DumpPropertyErrors(m_cPropSets, m_rgPropSets); if(m_hr==S_OK || m_hr==DB_S_ERRORSOCCURRED) { FreeProperties(&m_cPropSets, &m_rgPropSets) ; VARIANT vVar; VariantInit(&vVar); //Get the values of following properties. if(GetProperty(DBPROP_MAXOPENROWS, DBPROPSET_ROWSET, m_pIRowset, &vVar)) m_ulMaxOpenRows = V_I4(&vVar); else m_ulMaxOpenRows = 0; VariantClear(&vVar); return TRUE; } } } } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*--------------------------------------------------------------------- // @mfunc IConvertType // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_1() { return testIConvertType() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*--------------------------------------------------------------------- // @mfunc IColumnsInfo::GetColumnInfo // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_2() { return testGetColumnInfo((IUnknown*)m_pIRowset) ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*--------------------------------------------------------------------- // @mfunc IColumnsInfo::MapColumnIDs // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_3() { return testMapColumnIDs((IUnknown*)m_pIRowset) ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*--------------------------------------------------------------------- // @mfunc IAccessor // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_4() { return testIAccessor() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(5) //*--------------------------------------------------------------------- // @mfunc IRowsetInfo::GetProperties // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_5() { return testRowsetGetProp((IUnknown*)m_pIRowset) ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(6) //*--------------------------------------------------------------------- // @mfunc IRowsetInfo::GetReferencedRowset // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_6() { return testIRowsetInfoGetRefRowset() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(7) //*--------------------------------------------------------------------- // @mfunc IRowsetInfo::GetSpecification (Session) // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_7() { return testIRowsetInfoGetSpec() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc IRowsetInfo::GetSpecification (Command) // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_8() { return testIRowsetInfoGetSpecCmd() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(9) //*--------------------------------------------------------------------- // @mfunc IRowset (No Properties) // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_9() { return testIRowset2() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(10) //*--------------------------------------------------------------------- // @mfunc IRowset (Scroll_Back & Canholdrows) // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_10() { BOOL fPropSup = TRUE; if(!GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset)) { odtLog<GetColumnsRowset(NULL, cOptCols, rgOptCols, IID_IRowset, 0, NULL, (IUnknown**)&pIRowset), S_OK) TESTC(CheckColumnsRowset((IUnknown*) pIRowset, cOptCols, bBookmark)) tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgOptCols); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIColumnsRowset); return tTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc IRowsetLocate::Compare // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetNotUpdateable::Variation_13() { //Check if the provider supports IRowsetLocate interface. if(!GetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset)) { odtLog<DropTable(); SAFE_DELETE(m_pTable); ReleaseDBSession(); ReleaseDataSourceObject(); // {{ TCW_TERM_BASECLASS_CHECK2 return(CQuickTest::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCRowsetUpdateable) //*--------------------------------------------------------------------- //| Test Case: TCRowsetUpdateable - Rowset Interfaces (Updateable Rowset) //| Created: 4/1/98 //*--------------------------------------------------------------------- //*--------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCRowsetUpdateable::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CQuickTest::Init()) // }} { if(CHECK(m_hr = CreateDBSession(),S_OK)) { CTable* pTable = NULL; //Required for using some ExtraLib functions without using //the ExtraLib classes. g_pIDBInitialize = m_pIDBInitialize; g_pIOpenRowset = m_pIOpenRowset; //Create table with MIN_ROWS rows. if(CreateTable(&pTable, MIN_ROWS)) { SetTable(pTable, DELETETABLE_NO); LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE| DBPROPVAL_UP_DELETE| DBPROPVAL_UP_INSERT ; //Set the following properties. SetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetSettableProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; SetProperty(DBPROP_CANFETCHBACKWARDS,DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ; //Open a rowset with above properties set. m_hr=CreateOpenRowset(m_pTable, IID_IRowset, (IUnknown**)&m_pIRowset); if(FAILED(m_hr)) DumpPropertyErrors(m_cPropSets, m_rgPropSets); if(m_hr==S_OK || m_hr==DB_S_ERRORSOCCURRED) { FreeProperties(&m_cPropSets, &m_rgPropSets); //ExtraLib global. g_ulNextRow = m_pTable->CountRowsOnTable() + 10; //Get the values of following properties. if(!GetProperty(DBPROP_MAXOPENROWS, DBPROPSET_ROWSET, m_pIRowset, &m_ulMaxOpenRows)) m_ulMaxOpenRows = 0; if(GetProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET, m_pIRowset)) m_fFetchBackwards = TRUE; return TRUE; } } } } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*--------------------------------------------------------------------- // @mfunc IRowsetIdentity // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdateable::Variation_1() { return testIRowsetIdentity() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*--------------------------------------------------------------------- // @mfunc IRowset (various properties set) // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdateable::Variation_2() { return testIRowset() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*--------------------------------------------------------------------- // @mfunc IRowsetChange::SetData // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdateable::Variation_3() { //Check if the provider supports IRowsetChange interface. if(GetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset)) return testIRowsetChangeSet() ; odtLog<IsUsingITableDefinition() || (GetModInfo()->IsUsingITableDefinition() && !SupportedProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET, m_pIDBInitialize,ROWSET_INTERFACE)) || GetModInfo()->GetInsert()==INSERT_WITHPARAMS) && GetModInfo()->GetInsert()!=INSERT_COMMAND && m_pIDBCreateCommand && (m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandWithParameters,(IUnknown**)&pICommandWithParameters)==S_OK)) bUseInsertWithParams = TRUE; SAFE_RELEASE(pICommandWithParameters); //Cleanup and refresh the table. Delete all the rows and //insert original rows again, hence restoring table to //a fresh state. if(m_pTable) { ulRows = m_pTable->GetRowsOnCTable(); m_hr = m_pTable->DeleteRows(ALLROWS); if(m_hr == S_OK) for(DBCOUNTITEM i=0; iInsertWithParams(i+1, PRIMARY), S_OK); else CHECK(m_pTable->Insert(i+1, PRIMARY), S_OK); } m_pTable->DropTable(); } SAFE_DELETE(m_pTable); ReleaseDBSession(); ReleaseDataSourceObject(); // {{ TCW_TERM_BASECLASS_CHECK2 return(CQuickTest::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCCommand) //*--------------------------------------------------------------------- //| Test Case: TCCommand - Command Interfaces //| Created: 4/13/98 //*--------------------------------------------------------------------- //*--------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCCommand::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CQuickTest::Init()) // }} { HRESULT hr = S_OK; IDBCreateCommand* pIDBCreateCommand = NULL; // Get DB Session if(CHECK(hr = CreateDBSession(), S_OK)) { if(m_pIDBCreateCommand) { if(CHECK(hr = m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,(IUnknown **)&m_pICommand),S_OK)) { // Make sure DB Session returned is correct COMPARE(SUCCEEDED(hr=m_pICommand->GetDBSession(IID_IDBCreateCommand, (IUnknown **)&pIDBCreateCommand)),TRUE); if(hr==S_OK) COMPARE(VerifyEqualInterface(m_pIDBCreateCommand, pIDBCreateCommand), TRUE); SAFE_RELEASE(pIDBCreateCommand); //For ExtraLib functions. g_pIDBInitialize = m_pIDBInitialize; g_pIOpenRowset = m_pIOpenRowset; CTable* pTable = NULL; //Create table with MIN_ROWS rows. if(CreateTable(&pTable, MIN_ROWS)) { GetProperty(DBPROP_SQLSUPPORT, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &m_ulSQLSup); SetTable(pTable, DELETETABLE_NO); if(!m_pTable) return FALSE; //Create SQL stmt and set command text. if(!CHECK(m_pTable->ExecuteCommand(SELECT_ALLFROMTBL, IID_ICommand, NULL, NULL, NULL, NULL, EXECUTE_NEVER, 0, NULL, NULL, NULL, &m_pICommand), S_OK)) return FALSE; return TRUE; } else { odtLog<Prepare(1), S_OK)) { SAFE_RELEASE(pICommandPrepare); return TEST_FAIL; } SAFE_RELEASE(pICommandPrepare); } return testGetColumnInfo((IUnknown*)m_pICommand) ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*--------------------------------------------------------------------- // @mfunc IColumnsInfo::MapColumnIDs // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_3() { ICommandPrepare* pICommandPrepare = NULL; if(VerifyInterface(m_pICommand,IID_ICommandPrepare, COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare)) { if(!CHECK(pICommandPrepare->Prepare(1), S_OK)) { SAFE_RELEASE(pICommandPrepare); return TEST_FAIL; } SAFE_RELEASE(pICommandPrepare); } return testMapColumnIDs((IUnknown*)m_pICommand) ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*--------------------------------------------------------------------- // @mfunc ICommandProperties::GetProperties // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_4() { return testRowsetGetProp((IUnknown*)m_pICommand) ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(5) //*--------------------------------------------------------------------- // @mfunc ICommandProperties::SetProperties // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_5() { return testSetCmdProp() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(6) //*--------------------------------------------------------------------- // @mfunc IConvertType // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_6() { return testIConvertType() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(7) //*--------------------------------------------------------------------- // @mfunc ICommandText // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_7() { return testICmdText() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(8) //*--------------------------------------------------------------------- // @mfunc ICommand::GetDBSession // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_8() { return testICmdGetDBSession() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(9) //*--------------------------------------------------------------------- // @mfunc ICommand::Execute (set,exe,set,exe,set,exe) // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_9() { return testICmdExec1() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(10) //*--------------------------------------------------------------------- // @mfunc ICommand::Execute (set,exe,exe,exe) // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_10() { return testICmdExec2() ; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc IColumnsRowset::GetAvailableColumns // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_11() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; DBORDINAL cOptCols = 0; DBID* rgOptCols = NULL; ICommand* pICommand = NULL; ICommandPrepare* pICommandPrepare = NULL; //Create a command object. TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand, (IUnknown**)&pICommand), S_OK) //Set the command text to select all from table. TESTC_(SetCommandText(m_pIMalloc, pICommand, m_pTable, NULL, eSELECT, SELECT_ALLFROMTBL, NULL), S_OK) //If ICommandPrepare is supported, prepare the command. if(VerifyInterface(pICommand,IID_ICommandPrepare, COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare)) { TESTC_(pICommandPrepare->Prepare(1), S_OK) } hr=GetAvailableColumns((IUnknown*)pICommand, &cOptCols, &rgOptCols) ; if(hr==E_NOINTERFACE) { tTestResult = TEST_SKIPPED; goto CLEANUP; } else TESTC_(hr, S_OK) TESTC(CheckOptColumns(cOptCols, rgOptCols)) tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgOptCols); SAFE_RELEASE(pICommandPrepare); SAFE_RELEASE(pICommand); return tTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc IColumnsRowset::GetColumnsRowset // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_12() { TESTRESULT tTestResult = TEST_FAIL; HRESULT hr = S_OK; BOOL bBookmark = FALSE; DBORDINAL cOptCols = 0; DBID* rgOptCols = NULL; ICommand* pICommand = NULL; ICommandPrepare* pICommandPrepare = NULL; IColumnsRowset* pIColumnsRowset = NULL; IRowset* pIRowset = NULL; //Create a command object. TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand, (IUnknown**)&pICommand), S_OK) //Set the command text to select all from table. TESTC_(SetCommandText(m_pIMalloc, pICommand, m_pTable, NULL, eSELECT, SELECT_ALLFROMTBL, NULL), S_OK) //If ICommandPrepare is supported, prepare the command. if(VerifyInterface(pICommand,IID_ICommandPrepare, COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare)) { TESTC_(pICommandPrepare->Prepare(1), S_OK) } if(!VerifyInterface(pICommand,IID_IColumnsRowset, COMMAND_INTERFACE,(IUnknown**)&pIColumnsRowset)) { odtLog<GetColumnsRowset(NULL, cOptCols, rgOptCols, IID_IRowset, 0, NULL, (IUnknown**)&pIRowset), S_OK) TESTC(CheckColumnsRowset((IUnknown*) pIRowset, cOptCols, bBookmark)) tTestResult = TEST_PASS; CLEANUP: PROVIDER_FREE(rgOptCols); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIColumnsRowset); SAFE_RELEASE(pICommandPrepare); SAFE_RELEASE(pICommand); return tTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc ICommandPrepare::Prepare // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_13() { return testCmdPrep(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc ICommandPrepare::Unprepare // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_14() { return testCmdUnprep(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc ICommandWithParameters // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_15() { return testICmdWParam(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc IMultipleResults // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_16() { VARIANT vVar; VariantInit(&vVar); if(!GetProperty(DBPROP_MULTIPLERESULTS, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &vVar)) { odtLog<DropTable(); SAFE_DELETE(m_pTable); ReleaseDBSession(); ReleaseDataSourceObject(); // {{ TCW_TERM_BASECLASS_CHECK2 return(CQuickTest::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCOtherObjects) //*----------------------------------------------------------------------- //| Test Case: TCOtherObjects - Other Objects //| Created: 6/8/98 //*----------------------------------------------------------------------- //*----------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCOtherObjects::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CQuickTest::Init()) // }} { if(CHECK(m_hr = CreateDBSession(), S_OK)) { CTable* pTable = NULL; g_pIDBInitialize = m_pIDBInitialize; g_pIOpenRowset = m_pIOpenRowset; //Create table with MIN_ROWS rows. if(CreateTable(&pTable, MIN_ROWS)) { SetTable(pTable, DELETETABLE_NO); if(m_pTable) { g_ulNextRow = m_pTable->CountRowsOnTable() + 10; return TRUE; } } } } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc ErrorInterfaces // // @rdesc TEST_PASS or TEST_FAIL // int TCOtherObjects::Variation_1() { return testIError(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Transaction(Commit) // // @rdesc TEST_PASS or TEST_FAIL // int TCOtherObjects::Variation_2() { return testTransactionCommit(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Transaction(Abort) // // @rdesc TEST_PASS or TEST_FAIL // int TCOtherObjects::Variation_3() { return testTransactionAbort(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc StorageInterface // // @rdesc TEST_PASS or TEST_FAIL // int TCOtherObjects::Variation_4() { return testStorageObj(); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCOtherObjects::Terminate() { if(m_pTable) m_pTable->DropTable(); SAFE_DELETE(m_pTable); ReleaseDBSession(); ReleaseDataSourceObject(); // {{ TCW_TERM_BASECLASS_CHECK2 return(CQuickTest::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCBinder) //*----------------------------------------------------------------------- //| Test Case: TCBinder - Binder Interfaces //| Created: 9/22/98 //*----------------------------------------------------------------------- //*----------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCBinder::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CQuickTest::Init()) // }} { TBEGIN BOOL bTest; CTable* pTable = NULL; IGetDataSource* pIGetDataSource = NULL; //Get the root binder. bTest = CreateRootBinder(); if(bTest != TEST_PASS) return bTest; TESTC(DefaultObjectTesting(m_pIBindResource, BINDER_INTERFACE)) //bind to a session. TEST2C_(m_pIBindResource->Bind(NULL, m_pwszRowsetURL, DBBINDURLFLAG_READ, DBGUID_SESSION, IID_IOpenRowset, NULL, NULL, NULL, (IUnknown**)&m_pIOpenRowset), S_OK, DB_S_ERRORSOCCURRED) TESTC(VerifyInterface(m_pIOpenRowset,IID_IGetDataSource, SESSION_INTERFACE,(IUnknown**)&pIGetDataSource)) //get a dso. TESTC_(pIGetDataSource->GetDataSource(IID_IDBInitialize, (IUnknown**)&m_pIDBInitialize), S_OK) g_pIDBInitialize = m_pIDBInitialize; g_pIOpenRowset = m_pIOpenRowset; TESTC(CreateTable(&pTable, 5)) SetTable(pTable, DELETETABLE_NO); CLEANUP: SAFE_RELEASE(pIGetDataSource); TRETURN } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc IBindResource // // @rdesc TEST_PASS or TEST_FAIL // int TCBinder::Variation_1() { TBEGIN SAFE_RELEASE(m_pIRowset); //Should be NULL anyway. //bind to a rowset. TEST2C_(m_pIBindResource->Bind(NULL, m_pwszRowsetURL, DBBINDURLFLAG_READ, DBGUID_ROWSET, IID_IRowset, NULL, NULL, NULL, (IUnknown**)&m_pIRowset), S_OK, DB_S_ERRORSOCCURRED) TESTC(m_pIRowset != NULL) TESTC(DefaultObjectTesting(m_pIRowset, ROWSET_INTERFACE)) //Get the values of following properties. if(!GetProperty(DBPROP_MAXOPENROWS, DBPROPSET_ROWSET, m_pIRowset, &m_ulMaxOpenRows)) m_ulMaxOpenRows = 0; if(GetProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET, m_pIRowset)) m_fFetchBackwards = TRUE; TESTC(testIRowset()) CLEANUP: SAFE_RELEASE(m_pIRowset); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc ICreateRow // // @rdesc TEST_PASS or TEST_FAIL // int TCBinder::Variation_2() { TBEGIN HRESULT hr; ULONG_PTR ulVal = 0; WCHAR* pwszNewURL = NULL; IRow* pIRow = NULL; ICreateRow* pICreateRow = NULL; TESTC(VerifyInterface(m_pIBindResource,IID_ICreateRow, BINDER_INTERFACE,(IUnknown**)&pICreateRow)) hr=pICreateRow->CreateRow(NULL, m_pwszRowsetURL, DBBINDURLFLAG_READWRITE|DBBINDURLFLAG_OPENIFEXISTS, DBGUID_ROW, IID_IRow, NULL, NULL, NULL, &pwszNewURL, (IUnknown**)&pIRow); if(hr==S_OK || hr==DB_S_ERRORSOCCURRED) { TESTC(DefaultObjectTesting(pIRow, ROW_INTERFACE)) TESTC(testIRow(pIRow)) TESTC(pwszNewURL != NULL) COMPARE(wcscmp(pwszNewURL, m_pwszRowsetURL), 0); } else if(hr==DB_E_RESOURCEEXISTS) odtLog<Reset(), S_OK) //Set the init props on binder. TESTC(GetInitProps(&cPropSets, &rgPropSets)) //set a bunch of datasource and rowset props on the root //binder. SetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, &cPropSets, &rgPropSets, (void*)pbstrCC, DBTYPE_BSTR, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_MULTIPLECONNECTIONS, DBPROPSET_DATASOURCE, &cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET, &cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET, &cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET, &cPropSets, &rgPropSets) ; SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &cPropSets, &rgPropSets) ; TESTC_(hr=pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK) //bind to a rowset and verify props. TEST3C_(hr = m_pIBindResource->Bind(NULL, m_pwszRowsetURL, DBBINDURLFLAG_READ, DBGUID_ROWSET, IID_IRowset, NULL, NULL, NULL, (IUnknown**)&pIRowset), S_OK, DB_S_ERRORSOCCURRED, DB_E_ERRORSOCCURRED) if(hr == DB_E_ERRORSOCCURRED) { odtLog<GetSpecification(IID_IGetDataSource, (IUnknown**)&pIGDS), S_OK, S_FALSE) if(hr2 == S_OK) TESTC_(pIGDS->GetDataSource(IID_IDBProperties, (IUnknown**)&pIDBProp), S_OK) COMPARE(GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, pIRowset), TRUE); COMPARE(GetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET, pIRowset), TRUE); COMPARE(VerifyInterface(pIRowset,IID_IRowsetIdentity, ROWSET_INTERFACE,(IUnknown**)&pIRIdentity), TRUE); if(S_OK == hr) { COMPARE(GetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET, pIRowset), TRUE); COMPARE(VerifyInterface(pIRowset,IID_IRowsetLocate, ROWSET_INTERFACE,(IUnknown**)&pIRLocate), TRUE); COMPARE(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, pIRowset), TRUE); COMPARE(GetProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET, pIRowset), TRUE); if(pIDBProp) { COMPARE(GetProperty(DBPROP_MULTIPLECONNECTIONS, DBPROPSET_DATASOURCE, pIDBProp), TRUE); COMPARE(GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, pIDBProp, &vVar), TRUE); COMPARE(wcscmp(V_BSTR(&vVar), pbstrCC), 0); } } else // hr==DB_S_ERRORSOCCURRED { if(GetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET, pIRowset)) COMPARE(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, pIRowset), TRUE); if(GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, pIDBProp, &vVar)) COMPARE(wcscmp(V_BSTR(&vVar), pbstrCC), 0); } CLEANUP: VariantClear(&vVar); FreeProperties(&cPropSets, &rgPropSets); SAFE_RELEASE(pIRIdentity); SAFE_RELEASE(pIRLocate); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIRInfo); SAFE_RELEASE(pIGDS); SAFE_RELEASE(pIDBProp); SAFE_RELEASE(pIDBBProp); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc IDBBinderProperties - Reset // // @rdesc TEST_PASS or TEST_FAIL // int TCBinder::Variation_4() { TBEGIN HRESULT hr; ULONG ulIndex; //small no. ULONG_PTR ulMaxRows = 0; ULONG_PTR ulUpdt = 0; ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; VARIANT vrgDefault[4]; IRowset* pIRowset = NULL; IDBBinderProperties* pIDBBProp = NULL; for(ulIndex=0; ulIndex<4; ulIndex++) VariantInit(&vrgDefault[ulIndex]); TESTC(VerifyInterface(m_pIBindResource,IID_IDBBinderProperties, BINDER_INTERFACE,(IUnknown**)&pIDBBProp)) // //STEP-1 : Obtain the default values of 4 rowset properties and //store them in vrgDefault. // TESTC_(pIDBBProp->Reset(), S_OK) TESTC(GetInitProps(&cPropSets, &rgPropSets)) TESTC_(hr=pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK) TEST2C_(m_pIBindResource->Bind(NULL, m_pwszRowsetURL, DBBINDURLFLAG_READ, DBGUID_ROWSET, IID_IRowset, NULL, NULL, NULL, (IUnknown**)&pIRowset), S_OK, DB_S_ERRORSOCCURRED) TESTC(pIRowset != NULL) TESTC(GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, pIRowset, &vrgDefault[0])) TESTC(GetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET, pIRowset, &vrgDefault[1])) if(!GetProperty(DBPROP_MAXROWS, DBPROPSET_ROWSET, pIRowset, &vrgDefault[2])) VariantInit(&vrgDefault[2]); if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, pIRowset, &vrgDefault[3])) VariantInit(&vrgDefault[3]); SAFE_RELEASE(pIRowset); // //STEP-2 : Set the values of the 4 rowset properties. Then call //Reset(). After calling Reset(), Bind to a Rowset. // SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &cPropSets, &rgPropSets) ; SetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET, &cPropSets, &rgPropSets) ; SetProperty(DBPROP_MAXROWS, DBPROPSET_ROWSET, &cPropSets, &rgPropSets, (void*)25, DBTYPE_I4, DBPROPOPTIONS_OPTIONAL) ; SetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, &cPropSets, &rgPropSets, (void*)7, DBTYPE_I4, DBPROPOPTIONS_OPTIONAL) ; TEST2C_(hr=pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK, DB_S_ERRORSOCCURRED) TESTC_(pIDBBProp->Reset(), S_OK) FreeProperties(&cPropSets, &rgPropSets); TESTC(GetInitProps(&cPropSets, &rgPropSets)) TESTC_(hr=pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK) TEST2C_(m_pIBindResource->Bind(NULL, m_pwszRowsetURL, DBBINDURLFLAG_READ, DBGUID_ROWSET, IID_IRowset, NULL, NULL, NULL, (IUnknown**)&pIRowset), S_OK, DB_S_ERRORSOCCURRED) TESTC(pIRowset != NULL) // //STEP-3 : Obtain the 4 rowset properties from the rowset. Verify //that their values match the default ones stored in vrgDefault. // if(GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, pIRowset)) TESTC(V_BOOL(&vrgDefault[0]) == VARIANT_TRUE) else TESTC(V_BOOL(&vrgDefault[0]) == VARIANT_FALSE) if(GetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET, pIRowset)) TESTC(V_BOOL(&vrgDefault[1]) == VARIANT_TRUE) else TESTC(V_BOOL(&vrgDefault[1]) == VARIANT_FALSE) if(GetProperty(DBPROP_MAXROWS, DBPROPSET_ROWSET, pIRowset, &ulMaxRows)) TESTC(((ULONG_PTR)V_I4(&vrgDefault[2])) == ulMaxRows) else TESTC(V_VT(&vrgDefault[2]) == VT_EMPTY) if(GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, pIRowset, &ulUpdt)) TESTC(((ULONG_PTR)V_I4(&vrgDefault[3])) == ulUpdt) else TESTC(V_VT(&vrgDefault[3]) == VT_EMPTY) CLEANUP: for(ulIndex=0; ulIndex<4; ulIndex++) VariantClear(&vrgDefault[ulIndex]); FreeProperties(&cPropSets, &rgPropSets); SAFE_RELEASE(pIRowset); SAFE_RELEASE(pIDBBProp); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCBinder::Terminate() { if(m_pTable) m_pTable->DropTable(); SAFE_DELETE(m_pTable); SAFE_RELEASE(m_pIOpenRowset); SAFE_RELEASE(m_pIDBInitialize); SAFE_RELEASE(m_pIBindResource); // {{ TCW_TERM_BASECLASS_CHECK2 return(CQuickTest::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCRow) //*----------------------------------------------------------------------- //| Test Case: TCRow - Row Interfaces //| Created: 9/22/98 //*----------------------------------------------------------------------- //*----------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCRow::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CQuickTest::Init()) // }} { TBEGIN ULONG_PTR ulOleObj = 0; CTable* pTable = NULL; TESTC_(m_hr = CreateDBSession(),S_OK) //Required for using some ExtraLib functions. g_pIDBInitialize = m_pIDBInitialize; g_pIOpenRowset = m_pIOpenRowset; //Check if provider supports ROW Objects. If not, then SKIP //this test case. TESTC_PROVIDER(GetProperty(DBPROP_OLEOBJECTS, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulOleObj)) TESTC_PROVIDER((ulOleObj & DBPROPVAL_OO_ROWOBJECT) == DBPROPVAL_OO_ROWOBJECT) //Create a table with MIN_ROWS rows. TESTC(CreateTable(&pTable, MIN_ROWS)) SetTable(pTable, DELETETABLE_NO); TESTC(m_pTable != NULL) //Create the parent Rowset of the row objects used for testing //in the variations. m_pCRowset = new CRowset(); m_pCRowset->SetProperty(DBPROP_CANHOLDROWS); m_pCRowset->SetProperty(DBPROP_IRowsetIdentity); m_pCRowset->SetSettableProperty(DBPROP_IRowsetLocate); TESTC_(m_pCRowset->CreateRowset(USE_SUPPORTED_SELECT_ALLFROMTBL, IID_IRowset, m_pTable),S_OK); CLEANUP: TRETURN } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc IRow // // @rdesc TEST_PASS or TEST_FAIL // int TCRow::Variation_1() { TBEGIN HRESULT hr; DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRowsObtained = 0; HROW hRow = DB_NULL_HROW; HROW* rghRows = NULL; IRowsetInfo* pIRowsetInfo = NULL; IRowsetIdentity* pIRIdentity = NULL; TESTC_(m_pCRowset->RestartPosition(),S_OK) for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++) { CRowObject RowObj; //Get first row and create a row object on it. TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK) TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS) TESTC(DefaultObjectTesting(RowObj.pIRow(), ROW_INTERFACE)) //Veify the GetColumns method. TESTC(RowObj.VerifyGetColumns(ulIndex, m_pTable)) //Call GetSourceRowset and verify that the correct parent //is returned. TEST2C_(hr = RowObj.GetSourceRowset(IID_IRowsetInfo, (IUnknown**)&pIRowsetInfo, &hRow), S_OK, DB_E_NOSOURCEOBJECT) if(S_OK == hr) { TESTC(hRow != DB_NULL_HROW) TESTC(VerifyEqualInterface(pIRowsetInfo, m_pCRowset->pIRowset())) TESTC(VerifyInterface(pIRowsetInfo, IID_IRowsetIdentity, ROWSET_INTERFACE, (IUnknown**)&pIRIdentity)) TESTC_(pIRIdentity->IsSameRow(hRow, rghRows[0]), S_OK) CHECK(m_pCRowset->ReleaseRows(1, &hRow),S_OK); hRow = DB_NULL_HROW; } CHECK(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK); cRowsObtained = 0; PROVIDER_FREE(rghRows); SAFE_RELEASE(pIRIdentity); SAFE_RELEASE(pIRowsetInfo); } CLEANUP: m_pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); SAFE_RELEASE(pIRIdentity); SAFE_RELEASE(pIRowsetInfo); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc IGetSession // // @rdesc TEST_PASS or TEST_FAIL // int TCRow::Variation_2() { TBEGIN DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; IOpenRowset* pIOR = NULL; TESTC_(m_pCRowset->RestartPosition(),S_OK) for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++) { CRowObject RowObj; TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK) TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS) TESTC_(RowObj.GetSession(IID_IOpenRowset, (IUnknown**)&pIOR), S_OK) TESTC(VerifyEqualInterface(pIOR, m_pIOpenRowset)) TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK) cRowsObtained = 0; PROVIDER_FREE(rghRows); SAFE_RELEASE(pIOR); } CLEANUP: m_pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); SAFE_RELEASE(pIOR); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc IConvertType // // @rdesc TEST_PASS or TEST_FAIL // int TCRow::Variation_3() { TBEGIN DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; //Make sure these are NULL, although hey should be. SAFE_RELEASE(m_pICommand); SAFE_RELEASE(m_pIRowset); SAFE_RELEASE(m_pIRow); TESTC_(m_pCRowset->RestartPosition(),S_OK) for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++) { CRowObject RowObj; TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK) TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS) m_pIRow = RowObj.pIRow(); TESTC(testIConvertType()) m_pIRow = NULL; TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK) cRowsObtained = 0; PROVIDER_FREE(rghRows); } CLEANUP: m_pIRow = NULL; m_pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc IColumnsInfo // // @rdesc TEST_PASS or TEST_FAIL // int TCRow::Variation_4() { TBEGIN DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; TESTC_(m_pCRowset->RestartPosition(),S_OK) for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++) { CRowObject RowObj; TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK) TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS) TESTC(testColInfo2(&RowObj)) TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK) cRowsObtained = 0; PROVIDER_FREE(rghRows); } CLEANUP: m_pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc IColumnsInfo2 // // @rdesc TEST_PASS or TEST_FAIL // int TCRow::Variation_5() { TBEGIN DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; IColumnsInfo2* pICI2 = NULL; TESTC_(m_pCRowset->RestartPosition(),S_OK) for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++) { CRowObject RowObj; TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK) TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS) if(ulIndex==1) TESTC_PROVIDER(VerifyInterface(RowObj.pIRow(), IID_IColumnsInfo2, ROW_INTERFACE, (IUnknown**)&pICI2)) else TESTC(VerifyInterface(RowObj.pIRow(), IID_IColumnsInfo2, ROW_INTERFACE, (IUnknown**)&pICI2)) TESTC(testColInfo2(&RowObj, TRUE)) TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK) cRowsObtained = 0; PROVIDER_FREE(rghRows); SAFE_RELEASE(pICI2); } CLEANUP: m_pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); SAFE_RELEASE(pICI2); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc IGetRow // // @rdesc TEST_PASS or TEST_FAIL // int TCRow::Variation_6() { TBEGIN DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; WCHAR* pwszURL = NULL; IGetRow* pIGetRow = NULL; TESTC_(m_pCRowset->RestartPosition(),S_OK) TESTC(VerifyInterface(m_pCRowset->pIRowset(), IID_IGetRow, ROWSET_INTERFACE, (IUnknown**)&pIGetRow)) for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++) { CRowObject RowObj; TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK) //The following tests the GetRowFromHROW method. TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS) TESTC(RowObj.VerifyGetColumns(ulIndex, m_pTable)) //Now test the GetURLFromHROW method. TESTC_(pIGetRow->GetURLFromHROW(rghRows[0], &pwszURL), S_OK) TESTC((pwszURL != NULL) && (wcslen(pwszURL)>2)) TESTC(wcsstr(pwszURL, L":") != NULL) TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK) cRowsObtained = 0; PROVIDER_FREE(rghRows); SAFE_FREE(pwszURL); } CLEANUP: m_pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); SAFE_FREE(pwszURL); SAFE_RELEASE(pIGetRow); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc IGetSourceRow // // @rdesc TEST_PASS or TEST_FAIL // int TCRow::Variation_7() { TBEGIN HRESULT hr; DBCOUNTITEM ulIndex = 0; DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; DBID dbid = DBROWCOL_DEFAULTSTREAM; IGetSession* pIGS = NULL; IGetSourceRow* pIGetSourceRow = NULL; TESTC_(m_pCRowset->RestartPosition(),S_OK) for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++) { CRowObject RowObj; TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK) TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS) TEST2C_(hr=RowObj.Open(NULL, &dbid, DBGUID_STREAM, IID_IGetSourceRow, (IUnknown**)&pIGetSourceRow), S_OK, DB_E_BADCOLUMNID) if(hr==S_OK) { TEST2C_(hr=pIGetSourceRow->GetSourceRow(IID_IGetSession, (IUnknown**) &pIGS), S_OK, DB_E_NOSOURCEOBJECT) if(hr==S_OK) TESTC(VerifyEqualInterface(pIGS, RowObj.pIRow())) else TESTC(!pIGS) } TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK) cRowsObtained = 0; PROVIDER_FREE(rghRows); SAFE_RELEASE(pIGS); SAFE_RELEASE(pIGetSourceRow); } CLEANUP: m_pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); SAFE_RELEASE(pIGS); SAFE_RELEASE(pIGetSourceRow); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc IRowChange // // @rdesc TEST_PASS or TEST_FAIL // int TCRow::Variation_8() { TBEGIN DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; IRowChange* pIRowChange = NULL; CRowObject RowObj; TESTC_(m_pCRowset->RestartPosition(),S_OK) TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK) TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS) TESTC_PROVIDER(VerifyInterface(RowObj.pIRow(), IID_IRowChange, ROW_INTERFACE, (IUnknown**)&pIRowChange)) TESTC(testIRowChange(&RowObj)) CLEANUP: m_pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); SAFE_RELEASE(pIRowChange); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc IRowSchemaChange // // @rdesc TEST_PASS or TEST_FAIL // int TCRow::Variation_9() { TBEGIN DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; IRowSchemaChange* pIRowSchemaChange = NULL; CRowObject RowObj; TESTC_(m_pCRowset->RestartPosition(),S_OK) TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK) TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS) TESTC_PROVIDER(VerifyInterface(RowObj.pIRow(), IID_IRowSchemaChange, ROW_INTERFACE, (IUnknown**)&pIRowSchemaChange)) TESTC(testIRowSchemaChange(&RowObj)) CLEANUP: m_pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); SAFE_RELEASE(pIRowSchemaChange); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCRow::Terminate() { if(m_pTable) m_pTable->DropTable(); SAFE_DELETE(m_pTable); SAFE_DELETE(m_pCRowset); ReleaseDBSession(); ReleaseDataSourceObject(); // {{ TCW_TERM_BASECLASS_CHECK2 return(CQuickTest::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END //////////////////////////////////////////////////////////////////////// // Test Driver // //////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------- // The test driver (main) function. This runs all the tests (and all // variations in them) when QuikTest is run as a stand-alone executable. // void __cdecl main(int argc, char* argv[]) { HRESULT hr = S_OK ; CHAR* pszCmdLine = NULL ; CHAR* pszTemp = NULL; WCHAR* pwszCmdLine = NULL ; WCHAR* pwszProvName = NULL ; CLSID clsidProvider ; ITestCases* pTC = NULL ; IError* pIError = NULL; CBaseError* pCBError = NULL; TESTRESULT tResult = eVariationStatusNonExistent ; // VARIATION_STATUS VARIANT_BOOL fResult=VARIANT_FALSE; LONG dwResult=0; LONG cTotalVars=0; LONG cCaseCount=0; LONG cVarCount=0; LONG iTestNum=0; LONG iVarNum=0; ULONG cVarPassed=0; ULONG cVarFailed=0; //Total number of failures; not variations failed. ULONG cVarSkipped=0; ULONG cVarNonExistent=0; LONG cVarErrors = 0; LONG cVarWarnings = 0; LONG cModErrors = 0; LONG cModWarnings = 0; BSTR bstrModuleName = NULL; BSTR bstrModuleDesc = NULL; BSTR bstrCaseName = NULL; BSTR bstrCaseDesc = NULL; BSTR bstrVarDesc = NULL; if(hr != OleInitialize(NULL)) goto CLEANUP ; SetUseIMallocSpy(FALSE) ; //Get the command line. pszCmdLine = GetCommandLineA() ; //Remove the first arg, which is the executable name. //What's left is the Init string. if(argc>=2 && argv && argv[0] && argv[1]) { pszTemp = strstr(pszCmdLine, argv[0]); if(pszTemp) pszCmdLine = pszTemp + strlen(argv[0]) + 1 ; } else { OutputText(L"Expected at least 2 args on command line.\n"); goto CLEANUP; } //Now the command line consists of only the Init string. pwszCmdLine = ConvertToWCHAR(pszCmdLine) ; if(pwszCmdLine==NULL) { OutputText(L"Failed to convert Command Line.\n"); goto CLEANUP; } //Create a temporary CModInfo to use it's member function //GetInitStringValue to get the provider name from the //init string. Donot check for its return value. It will return //false since we passed in a NULL. CreateModInfo(NULL); GetModInfo()->SetInitString(pwszCmdLine) ; if(!GetModInfo()->GetInitStringValue(L"PROVIDER", &pwszProvName)) { OutputText(L"Failed to get the Provider Name.\n"); OutputText(L"Include PROVIDER=... in the Init String.\n"); goto CLEANUP; } ReleaseModInfo(NULL); //Destroyed the temporary CModInfo. //From provider name get class ID. if(FAILED(hr = CLSIDFromProgID(pwszProvName , &clsidProvider))) hr = CLSIDFromString(pwszProvName , &clsidProvider) ; if(FAILED(hr)) { OutputText(L"Failed to get CLSID from Provider Name.\n"); goto CLEANUP; } //Initialize the Global Module Data. SetGlobalModuleData() ; g_pThisTestModule->m_pwszInitString = SYSSTRING_ALLOC(pwszCmdLine) ; g_pThisTestModule->m_ProviderClsid = clsidProvider ; //This stmt is not required. It gets set to this by default. g_pThisTestModule->m_clsctxProvider = CLSCTX_INPROC_SERVER; //Create and initialize the CModInfo which will be used throughout //the test. if(!ModuleInit(g_pThisTestModule)) { OutputText(L"ModuleInit failed.\n"); goto CLEANUP; } //Create an error class to be used when run as a stand-alone //executable. pCBError = new CBaseError; if(pCBError == NULL) { OutputText(L"Failed to create an Error Object.\n"); goto CLEANUP; } //Get the IError interface from our error object. pCBError->QueryInterface(IID_IError, (void**)&pIError); if(pIError == NULL) { OutputText(L"Failed to get the IError interface.\n"); goto CLEANUP; } //Set the obtained IError as our Error interface to use. GetModInfo()->GetErrorObject()->SetErrorInterface(pIError); //Get name and description of the module and print it alongwith //the initialization string. g_pThisTestModule->GetName(&bstrModuleName); g_pThisTestModule->GetDescription(&bstrModuleDesc); OutputText(L" \n") ; OutputText(L"-------------------------------------------------------------------------------\n") ; OutputText(L"ModuleName: %s\n",bstrModuleName) ; OutputText(L"ModuleDesc: %s\n",bstrModuleDesc) ; OutputText(L"Initialization: %s\n",pwszCmdLine) ; OutputText(L"-------------------------------------------------------------------------------\n") ; //Get number of test cases. g_pThisTestModule->GetCaseCount(&cCaseCount); //Initialize error and warning counters. pCBError->ResetModErrors(); pCBError->ResetModWarnings(); //Loop through the Test Cases. for( iTestNum=0; iTestNumResetCaseErrors(); pCBError->ResetCaseWarnings(); //Get the test case. if(!CHECK(g_pThisTestModule->GetCase(iTestNum,&pTC), S_OK)) goto CLEANUP; if(pTC==NULL) { OutputText(L"Failed to get test case (%d).\n", iTestNum+1); continue; } pTC->GetVariationCount(&cVarCount) ; pTC->GetName(&bstrCaseName); pTC->GetDescription(&bstrCaseDesc); OutputText(L" \n"); OutputText(L"%s: %s.\n",bstrCaseName,bstrCaseDesc); //Increment total variation count by number of vars in this //test case. cTotalVars += cVarCount; //Call the Init() function of this test case. If fails, goto //terminate(). pTC->Init(&dwResult); if(dwResult == (LONG)TEST_FAIL) { //If Init fails, then all variations within that TestCase //are counted as failed. cVarFailed += cVarCount; OutputText(L"Init failed.\n"); goto TERMINATE; } else if(dwResult == (LONG)TEST_SKIPPED) { //If Init is skipped, then all variations within that //TestCase are counted as skipped. cVarSkipped += cVarCount; //Skip all variations in this test case. goto TERMINATE; } //Loop through the variations. for( iVarNum=0; iVarNumResetVarErrors(); pCBError->ResetVarWarnings(); pTC->GetVariationDesc(iVarNum, &bstrVarDesc); OutputText(L"\tVariation (%d) %s.\n",iVarNum+1, bstrVarDesc); tResult = eVariationStatusNonExistent; //Execute the variation. try { pTC->ExecuteVariation(iVarNum, &tResult) ; } catch(...) { OutputText(L"\tEXCEPTION thrown.\n"); tResult = TEST_FAIL; } //Get error and warning count of this variation. pCBError->GetVarErrors(&cVarErrors); pCBError->GetVarWarnings(&cVarWarnings); if(cVarErrors > 0) tResult = TEST_FAIL; //Display Result of the variation. switch(tResult) { case TEST_PASS: if(cVarWarnings > 0) OutputText(L"\tWARNING\n"); else OutputText(L"\tPASS\n"); cVarPassed++; break; case TEST_FAIL: OutputText(L"\tFAIL ******** FAIL\n"); if(cVarErrors==0) cVarFailed++; else cVarFailed += cVarErrors; break; case TEST_SKIPPED: OutputText(L"\tSKIPPED\n"); cVarSkipped++; break; default: OutputText(L"\tNON-EXISTENT\n"); cVarNonExistent++; break; }//switch OutputText(L"\n"); SAFE_SYSFREE(bstrVarDesc); } TERMINATE: //Call the terminate() function of this test case. pTC->Terminate(&fResult) ; SAFE_SYSFREE(bstrCaseName); SAFE_SYSFREE(bstrCaseDesc); SAFE_RELEASE(pTC); cVarCount = 0; } //Get error and warning count of entire module. pCBError->GetModErrors(&cModErrors); pCBError->GetModWarnings(&cModWarnings); OutputText(L" \n"); OutputText(L"-------------------------------------------------------------------------------\n") ; OutputText(L"FAILURES = %d\t(Total number of errors in entire test)\n", cVarFailed); OutputText(L"Warnings = %d\t(Total number of warnings in entire test)\n", cModWarnings); OutputText(L"Skipped = %d\t(Number of variations skipped)\n", cVarSkipped); OutputText(L"Passed = %d/%d\t(Number of variations passed and skipped / Number of variations run)\n", cVarPassed+cVarSkipped, cTotalVars); OutputText(L"Pass Percent = %d\t(percentage of above ratio)\n", (cVarPassed+cVarSkipped)*100/cTotalVars); OutputText(L"-------------------------------------------------------------------------------\n") ; //Terminate module. Releases CModInfo. if(!ModuleTerminate(g_pThisTestModule)) OutputText(L"ModuleTerminate Failed.\n"); CLEANUP: SAFE_RELEASE(pIError); SAFE_FREE(pwszCmdLine); SAFE_FREE(pwszProvName); SAFE_SYSFREE(bstrModuleName); SAFE_SYSFREE(bstrModuleDesc); OleUninitialize() ; }