//-------------------------------------------------------------------- // Microsoft OLE DB Test // // Copyright (C) 1995-2000 Microsoft Corporation // // @doc // // @module Threads.cpp | This module tests the OLEDB threading support // // disable warning: C4312 Conversion to bigger-size warning. // For example, "type cast": conversion from "int" to "int*_ptr64" of greater size. #pragma warning(disable: 4312) ////////////////////////////////////////////////////////////////// // Includes // ////////////////////////////////////////////////////////////////// #include "MODStandard.hpp" // Standard headers #include "Threads.h" // Threads header #include "ExtraLib.h" ////////////////////////////////////////////////////////////////// // Defines // ////////////////////////////////////////////////////////////////// #define MAX_ITERATIONS 7 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Module Values // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // {{ TCW_MODULE_GLOBALS DECLARE_MODULE_CLSID = { 0x1e9af4d0, 0xca41, 0x11cf, { 0xbc, 0x5d, 0x00, 0xa0, 0xc9, 0x0d, 0x80, 0x7a }}; DECLARE_MODULE_NAME("Threads"); DECLARE_MODULE_OWNER("Microsoft"); DECLARE_MODULE_DESCRIP("Threads Testing for OLEDB"); DECLARE_MODULE_VERSION(835236726); // TCW_WizardVersion(2) // TCW_Automation(True) // }} TCW_MODULE_GLOBALS_END ////////////////////////////////////////////////////////////////// // VerifyThreadingModel // ////////////////////////////////////////////////////////////////// BOOL VerifyThreadingModel() { return VerifyThreadingModel(PROVIDER_CLSID, L"Free", GetModInfo()->GetClassContext()) || VerifyThreadingModel(PROVIDER_CLSID, L"Both", GetModInfo()->GetClassContext()); } //-------------------------------------------------------------------- // @func Module level initialization routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems // BOOL ModuleInit(CThisTestModule * pThisTestModule) { //CommonInit //Need to actually call this first, since it sets up error objects... BOOL bReturn = CommonModuleInit(pThisTestModule, IID_IRowset, TEN_ROWS); //This Threading Test assumes FreeThreaded or Both //It is designed to pass pointers freely between threads, it will NOT //work in apartment model only environments... if(bReturn && !VerifyThreadingModel()) { TOUTPUT("This test is designed for FreeThreaded providers, ThreadingModel=\"Free\" or \"Both\""); return TEST_SKIPPED; } return bReturn; } //-------------------------------------------------------------------- // @func Module level termination routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems // BOOL ModuleTerminate(CThisTestModule * pThisTestModule) { return CommonModuleTerminate(pThisTestModule); } ////////////////////////////////////////////////////////////////// // Class CThreads // // Used to create multiple instantes of CTestCases even though our // privlib is really not designed for it, quite a useful hack... ////////////////////////////////////////////////////////////////// class CThreads : public CRowset { public: //Constructors CThreads(WCHAR* pwszTestCaseName = INVALID(WCHAR*)); virtual ~CThreads(); //methods //IUnknown static ULONG WINAPI Thread_QI(LPVOID pv); static ULONG WINAPI Thread_AddRef(LPVOID pv); static ULONG WINAPI Thread_Release(LPVOID pv); //DataSource (IDBProperties / IDBInitialize) static ULONG WINAPI Thread_IDBInitialize(LPVOID pv); static ULONG WINAPI Thread_IDBUninitialize(LPVOID pv); static ULONG WINAPI Thread_NewDSOInitialize(LPVOID pv); static ULONG WINAPI Thread_IDBGetPropertyInfo(LPVOID pv); static ULONG WINAPI Thread_IDBGetProperties(LPVOID pv); static ULONG WINAPI Thread_IDBSetProperties(LPVOID pv); //ICommand static ULONG WINAPI Thread_CommandCancel(LPVOID pv); static ULONG WINAPI Thread_CommandExecute(LPVOID pv); //ICommandPrepare static ULONG WINAPI Thread_CommandPrepare(LPVOID pv); static ULONG WINAPI Thread_CommandUnPrepare(LPVOID pv); //ICommandProperties static ULONG WINAPI Thread_GetCommandProperties(LPVOID pv); static ULONG WINAPI Thread_SetCommandProperties(LPVOID pv); //ICommandText static ULONG WINAPI Thread_SetCommandText(LPVOID pv); static ULONG WINAPI Thread_GetCommandText(LPVOID pv); //ICommandWithParameters static ULONG WINAPI Thread_SetDefaultValues(LPVOID pv); static ULONG WINAPI Thread_GetDefaultValues(LPVOID pv); //IAccessor static ULONG WINAPI Thread_CreateAccessor(LPVOID pv); static ULONG WINAPI Thread_GetBindings(LPVOID pv); static ULONG WINAPI Thread_ReleaseAccessor(LPVOID pv); //IColumnsInfo static ULONG WINAPI Thread_GetColumnsInfo(LPVOID pv); //IErrorRecords static ULONG WINAPI Thread_AddErrorRecord(LPVOID pv); static ULONG WINAPI Thread_GetErrorInfo(LPVOID pv); //Session (IDBCreateCommand / IDBCreateSession / ITableDefinition) static ULONG WINAPI Thread_IDBCreateCommand(LPVOID pv); static ULONG WINAPI Thread_IDBCreateSession(LPVOID pv); static ULONG WINAPI Thread_IDBCreateTable(LPVOID pv); static ULONG WINAPI Thread_AddColumn(LPVOID pv); static ULONG WINAPI Thread_DropColumn(LPVOID pv); //Schema static ULONG WINAPI Thread_GetSchemaRowset(LPVOID pv); static ULONG WINAPI Thread_GetSchemaInfo(LPVOID pv); //Class Factory static ULONG WINAPI Thread_GetClassFactory(LPVOID pv); static ULONG WINAPI Thread_CreateInstance(LPVOID pv); //IPersist static ULONG WINAPI Thread_PersistFileSave(LPVOID pv); static ULONG WINAPI Thread_PersistFileLoad(LPVOID pv); //IConnectionPoint static ULONG WINAPI Thread_CreateListener(LPVOID pv); //ITransaction static ULONG WINAPI Thread_StartTransaction(LPVOID pv); static ULONG WINAPI Thread_Commit(LPVOID pv); static ULONG WINAPI Thread_Abort(LPVOID pv); //IRowset static ULONG WINAPI Thread_AddRefRows(LPVOID pv); static ULONG WINAPI Thread_ReleaseRows(LPVOID pv); static ULONG WINAPI Thread_GetNextRows(LPVOID pv); static ULONG WINAPI Thread_GetData(LPVOID pv); static ULONG WINAPI Thread_RestartPosition(LPVOID pv); //IOpenRowset static ULONG WINAPI Thread_OpenRowset(LPVOID pv); //IRowsetChange static ULONG WINAPI Thread_SetData(LPVOID pv); static ULONG WINAPI Thread_DeleteRows(LPVOID pv); static ULONG WINAPI Thread_InsertRow(LPVOID pv); //IRowsetInfo static ULONG WINAPI Thread_GetRowsetProperties(LPVOID pv); static ULONG WINAPI Thread_GetSpecification(LPVOID pv); //IRowsetWithparameters static ULONG WINAPI Thread_Requery(LPVOID pv); //IRowsetResynch static ULONG WINAPI Thread_ResynchRows(LPVOID pv); static ULONG WINAPI Thread_GetVisibleData(LPVOID pv); //IRowsetLocate static ULONG WINAPI Thread_GetRowsAt(LPVOID pv); static ULONG WINAPI Thread_GetRowsByBookmark(LPVOID pv); //IRowsetUpdate static ULONG WINAPI Thread_GetOriginalData(LPVOID pv); static ULONG WINAPI Thread_GetPendingRows(LPVOID pv); static ULONG WINAPI Thread_GetRowStatus(LPVOID pv); static ULONG WINAPI Thread_Undo(LPVOID pv); static ULONG WINAPI Thread_Update(LPVOID pv); //IMultipleResults static ULONG WINAPI Thread_GetResult(LPVOID pv); protected: //data private: //data pointers }; CThreads::CThreads(WCHAR* pwszTestCaseName) : CRowset(pwszTestCaseName) { //private } CThreads::~CThreads() { } /////////////////////////////////////////////////////////// // Thread routines - IUnknown // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_QI(LPVOID pv) { THREAD_BEGIN //Thread Stack Variables IUnknown* pIUnknown = (IUnknown*)THREAD_FUNC; IID* priid = (IID*)THREAD_ARG1; ASSERT(pIUnknown && priid); HRESULT hr = S_OK; ThreadSwitch(); //Let the other threads Catch up for(ULONG i=0; iAddRef(); ThreadSwitch(); //Let the other thread(s) catch up THREAD_END(ulRefCount); } ULONG CThreads::Thread_Release(LPVOID pv) { THREAD_BEGIN ULONG ulRefCount = 0; //Thread Stack Variables IUnknown* pThis = (IUnknown*)THREAD_FUNC; ASSERT(pThis); ThreadSwitch(); //Let the other threads Catch up ulRefCount = pThis->Release(); ThreadSwitch(); //Let the other thread(s) catch up THREAD_END(ulRefCount); } /////////////////////////////////////////////////////////// // Thread routines - IDBProperties // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_IDBGetPropertyInfo(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables IDBProperties* pIDBProperties = (IDBProperties*)THREAD_FUNC; ULONG cPropIDSets = (ULONG)THREAD_ARG1; DBPROPIDSET* rgPropIDSets = (DBPROPIDSET*)THREAD_ARG2; ASSERT(pIDBProperties); //Local Variables ULONG cPropInfoSets = 0; DBPROPINFOSET* rgPropInfoSets = NULL; WCHAR* pwszStringBuffer = NULL; ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; iGetPropertyInfo(cPropIDSets, rgPropIDSets, &cPropInfoSets, &rgPropInfoSets, &pwszStringBuffer),S_OK) TESTC(cPropInfoSets!=0 && rgPropInfoSets!=NULL && pwszStringBuffer!=NULL); ::FreeProperties(&cPropInfoSets, &rgPropInfoSets, &pwszStringBuffer); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: ::FreeProperties(&cPropInfoSets, &rgPropInfoSets, &pwszStringBuffer); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IDBProperties // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_IDBGetProperties(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables IDBProperties* pIDBProperties = (IDBProperties*)THREAD_FUNC; ULONG cPropIDSets = (ULONG)THREAD_ARG1; DBPROPIDSET* rgPropIDSets = (DBPROPIDSET*)THREAD_ARG2; ASSERT(pIDBProperties); //Local Variables ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; iGetProperties(cPropIDSets, rgPropIDSets, &cPropSets, &rgPropSets),S_OK) TESTC(rgPropSets!=NULL) ::FreeProperties(&cPropSets,&rgPropSets); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: ::FreeProperties(&cPropSets,&rgPropSets); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IDBProperties // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_IDBSetProperties(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables IDBProperties* pIDBProperties = (IDBProperties*)THREAD_FUNC; ULONG cPropSets = (ULONG)THREAD_ARG1; DBPROPSET* rgPropSets = (DBPROPSET*)THREAD_ARG2; ASSERT(pIDBProperties); ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; iSetProperties(cPropSets, rgPropSets),S_OK) } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IDBInitialize // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_IDBInitialize(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables IDBInitialize* pIDBInitialize = (IDBInitialize*)THREAD_FUNC; HRESULT hrExpected = (HRESULT)THREAD_ARG1; ASSERT(pIDBInitialize); ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; iInitialize(), S_OK, hrExpected); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_END(hr); } ULONG CThreads::Thread_IDBUninitialize(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables IDBInitialize* pIDBInitialize = (IDBInitialize*)THREAD_FUNC; HRESULT hrExpected = (HRESULT)THREAD_ARG1; ASSERT(pIDBInitialize); ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; iUninitialize(), S_OK, hrExpected); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IDBInitialize // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_NewDSOInitialize(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables IDBInitialize* pIDBInitialize = NULL; IDBProperties* pIDBProperties = NULL; CThreads* pThis = (CThreads*)THREAD_FUNC; ULONG cPropSets = (ULONG)THREAD_ARG1; DBPROPSET* rgPropSets = (DBPROPSET*)THREAD_ARG2; HRESULT hrExpected = (HRESULT)THREAD_ARG3; HRESULT hrExpected2 = (HRESULT)THREAD_ARG4; ASSERT(pThis == NULL); ThreadSwitch(); //Let the other thread(s) catch up //Create the new DSO TESTC_(CreateNewDSO(NULL, IID_IDBInitialize,(IUnknown**)&pIDBInitialize, CREATEDSO_NONE),S_OK); //SetProperties TESTC_(QI(pIDBInitialize, IID_IDBProperties, (void**)&pIDBProperties),S_OK); TESTC_(pIDBProperties->SetProperties(cPropSets, rgPropSets),S_OK); //IDBInitialize TEST3C_(hr = pIDBInitialize->Initialize(), S_OK, hrExpected, hrExpected2); ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIDBInitialize); SAFE_RELEASE(pIDBProperties); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - ICommand // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_CommandCancel(LPVOID pv) { THREAD_BEGIN HRESULT hr; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; HRESULT hrExpected = (HRESULT)THREAD_ARG1; ASSERT(pThis); //Local Variables ThreadSwitch(); //Let the other thread(s) catch up if(pThis->GetCommandSupport()) { for(ULONG i=0; ipICommand()->Cancel(), S_OK, hrExpected); } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_END(hr); } ULONG CThreads::Thread_CommandExecute(LPVOID pv) { THREAD_BEGIN HRESULT hr; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; HRESULT hrExpected = (HRESULT)THREAD_ARG1; ASSERT(pThis); //Local Variables IRowset* pIRowset = NULL; ThreadSwitch(); //Let the other thread(s) catch up if(pThis->GetCommandSupport()) { for(ULONG i=0; ipICommand()->Execute(NULL,IID_IRowset,NULL,NULL,(IUnknown**)&pIRowset); TEST2C_(hr, S_OK, hrExpected); //Verify Result... TESTC(VerifyOutputInterface(hr, IID_IRowset, (IUnknown**)&pIRowset)); SAFE_RELEASE(pIRowset) } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIRowset) THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - ICommandPrepare // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_CommandPrepare(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables ICommandPrepare* pICommandPrepare = NULL; ThreadSwitch(); //Let the other thread(s) catch up if(pThis->GetCommandSupport()) { if(hr = QI(pThis->m_pICommand, IID_ICommandPrepare, (void**)&pICommandPrepare)==S_OK) { for(ULONG i=0; iPrepare(1),S_OK) } } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pICommandPrepare); THREAD_END(hr); } ULONG CThreads::Thread_CommandUnPrepare(LPVOID pv) { THREAD_BEGIN HRESULT hr; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; HRESULT hrExpected = (HRESULT)THREAD_ARG1; ASSERT(pThis); //Local Variables ICommandPrepare* pICommandPrepare = NULL; ThreadSwitch(); //Let the other thread(s) catch up if(pThis->GetCommandSupport()) { if(QI(pThis->m_pICommand,IID_ICommandPrepare,(void**)&pICommandPrepare)==S_OK) { for(ULONG i=0; iUnprepare(); TEST2C_(hr, S_OK, hrExpected); } } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pICommandPrepare); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - ICommandProperties // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_GetCommandProperties(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ULONG cPropIDSets = (ULONG)THREAD_ARG1; DBPROPIDSET* rgPropIDSets = (DBPROPIDSET*)THREAD_ARG2; ASSERT(pThis); //Local Variables ICommandProperties* pICommandProperties = NULL; ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; ThreadSwitch(); //Let the other thread(s) catch up if(pThis->GetCommandSupport()) { TESTC_(hr = QI(pThis->m_pICommand,IID_ICommandProperties,(void**)&pICommandProperties),S_OK) for(ULONG i=0; iGetProperties(cPropIDSets, rgPropIDSets, &cPropSets, &rgPropSets),S_OK) if(cPropIDSets) TESTC(rgPropSets!=NULL && rgPropSets[0].cProperties==cPropIDSets); ::FreeProperties(&cPropSets,&rgPropSets); } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pICommandProperties); ::FreeProperties(&cPropSets,&rgPropSets); THREAD_END(hr); } ULONG CThreads::Thread_SetCommandProperties(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ULONG cPropSets = (ULONG)THREAD_ARG1; DBPROPSET* rgPropSets = (DBPROPSET*)THREAD_ARG2; ASSERT(pThis); //Local Variables ICommandProperties* pICommandProperties = NULL; ThreadSwitch(); //Let the other thread(s) catch up if(pThis->GetCommandSupport()) { TESTC_(hr = QI(pThis->m_pICommand,IID_ICommandProperties,(void**)&pICommandProperties),S_OK) for(ULONG i=0; iSetProperties(cPropSets, rgPropSets),S_OK) } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pICommandProperties); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - ICommandText // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_SetCommandText(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; WCHAR* pwszCommandText = (WCHAR*)THREAD_ARG1; ASSERT(pThis); //Local Variables ICommandText* pICommandText = NULL; ThreadSwitch(); //Let the other thread(s) catch up if(pThis->GetCommandSupport()) { TESTC_(hr = QI(pThis->pICommand(),IID_ICommandText,(void**)&pICommandText),S_OK) for(ULONG i=0; iSetCommandText(DBGUID_DEFAULT, pwszCommandText),S_OK) } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pICommandText); THREAD_END(hr); } ULONG CThreads::Thread_GetCommandText(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables WCHAR* pwszCommandText = NULL; ICommandText* pICommandText = NULL; ThreadSwitch(); //Let the other thread(s) catch up if(pThis->GetCommandSupport()) { TESTC_(hr = QI(pThis->pICommand(),IID_ICommandText,(void**)&pICommandText),S_OK) for(ULONG i=0; iGetCommandText(NULL,&pwszCommandText),S_OK) PROVIDER_FREE(pwszCommandText); } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pICommandText); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - ICommandWithParameters // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_SetDefaultValues(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables ThreadSwitch(); //Let the other thread(s) catch up //TODO V2 ThreadSwitch(); //Let the other thread(s) catch up THREAD_END(hr); } ULONG CThreads::Thread_GetDefaultValues(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables ThreadSwitch(); //Let the other thread(s) catch up //TODO V2 ThreadSwitch(); //Let the other thread(s) catch up THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IAccessor // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_CreateAccessor(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); DBORDINAL cBindings = pThis->m_cBindings; DBBINDING* rgBinding = pThis->m_rgBinding; DBLENGTH cbRowSize = pThis->m_cRowSize; HACCESSOR rghAccessors[MAX_ITERATIONS]; ThreadSwitch(); //Let the other thread(s) catch up ULONG i; for(ULONG i=0; ipIAccessor()->CreateAccessor(DBACCESSOR_ROWDATA,cBindings,rgBinding,cbRowSize,&rghAccessors[i],NULL),S_OK) } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: for(i=0; ipIAccessor()->ReleaseAccessor(rghAccessors[i], NULL); } THREAD_END(hr); } ULONG CThreads::Thread_GetBindings(LPVOID pv) { THREAD_BEGIN //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; HACCESSOR* phAccessor = (HACCESSOR*)THREAD_ARG1; HRESULT hrExpected = (HRESULT)THREAD_ARG2; ASSERT(pThis && phAccessor); //Local Variables DBACCESSORFLAGS dwAccessorFlags = 0; DBORDINAL cBindings = 0; DBBINDING* rgBinding = NULL; HRESULT hr = S_OK; ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; ipIAccessor()->GetBindings(*phAccessor,&dwAccessorFlags,&cBindings,&rgBinding); TEST2C_(hr, S_OK, hrExpected); PROVIDER_FREE(rgBinding); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: PROVIDER_FREE(rgBinding); THREAD_END(hr); } ULONG CThreads::Thread_ReleaseAccessor(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; HACCESSOR* phAccessor = (HACCESSOR*)THREAD_ARG1; ASSERT(pThis && phAccessor); //Local Variables ThreadSwitch(); //Let the other thread(s) catch up TESTC_(hr = pThis->pIAccessor()->ReleaseAccessor(*phAccessor,NULL),S_OK) ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IColumnsInfo // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_GetColumnsInfo(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables DBORDINAL i,cColumns = 0; DBCOLUMNINFO* rgInfo = NULL; WCHAR* pwszStringsBuffer = NULL; IColumnsInfo* pIColInfo = NULL; TESTC_(hr = QI(pThis->pIRowset(),IID_IColumnsInfo,(void**)&pIColInfo),S_OK) ThreadSwitch(); //Let the other threads Catch up for(i=0; iGetColumnInfo(&cColumns,&rgInfo,&pwszStringsBuffer),S_OK) PROVIDER_FREE(rgInfo); PROVIDER_FREE(pwszStringsBuffer); } ThreadSwitch(); //Let the other threads Catch up CLEANUP: PROVIDER_FREE(rgInfo); PROVIDER_FREE(pwszStringsBuffer); SAFE_RELEASE(pIColInfo); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IErrorRecords // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_AddErrorRecord(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); IErrorInfo* pIErrorInfo = NULL; IErrorRecords* pIErrorRecords = NULL; ISupportErrorInfo* pISupportErrorInfo = NULL; ERRORINFO ErrorInfo[1]; ErrorInfo[0].hrError = DB_E_DELETEDROW; ErrorInfo[0].dwMinor = 0; ErrorInfo[0].clsid = CLSID_TESTMODULE; ErrorInfo[0].iid = IID_IRowset; ErrorInfo[0].dispid = DISPID_VALUE; //Cause an error to occur hr = QI(pThis->pIRowset(), IID_NULL, NULL); //Obtain the error object, from OLE Automation TESTC_PROVIDER(hr = QI(pThis->pIRowset(),IID_ISupportErrorInfo,(void**)&pISupportErrorInfo)==S_OK); TESTC_PROVIDER(hr = pISupportErrorInfo->InterfaceSupportsErrorInfo(IID_IRowset)==S_OK) QTESTC_(hr = GetErrorInfo(NULL,&pIErrorInfo),S_OK) TESTC_(hr = QI(pIErrorInfo,IID_IErrorRecords,(void**)&pIErrorRecords),S_OK) //Local Variables ThreadSwitch(); //Let the other thread(s) catch up //Now after all the Junk, we can actually add an error record... hr = pIErrorRecords->AddErrorRecord(&ErrorInfo[0],IDENTIFIER_SDK_ERROR,NULL,NULL,0); ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIErrorInfo); SAFE_RELEASE(pIErrorRecords); SAFE_RELEASE(pISupportErrorInfo); THREAD_END(hr); } ULONG CThreads::Thread_GetErrorInfo(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); IErrorInfo* pIErrorInfo = NULL; IErrorInfo* pIOutErrorInfo = NULL; IErrorRecords* pIErrorRecords = NULL; ISupportErrorInfo* pISupportErrorInfo = NULL; //Cause an error to occur hr = QI(pThis->pIRowset(), IID_NULL, NULL); //Obtain the error object, from OLE Automation TESTC_PROVIDER(hr = QI(pThis->pIRowset(),IID_ISupportErrorInfo,(void**)&pISupportErrorInfo)==S_OK); TESTC_PROVIDER(hr = pISupportErrorInfo->InterfaceSupportsErrorInfo(IID_IRowset)==S_OK) QTESTC_(hr = GetErrorInfo(NULL,&pIErrorInfo),S_OK) TESTC_(hr = QI(pIErrorInfo,IID_IErrorRecords,(void**)&pIErrorRecords),S_OK) //Local Variables ThreadSwitch(); //Let the other thread(s) catch up //Now after all the Junk, we can actually get the error info... hr = pIErrorRecords->GetErrorInfo(0,GetSystemDefaultLCID(),&pIOutErrorInfo); ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIErrorInfo); SAFE_RELEASE(pIOutErrorInfo); SAFE_RELEASE(pIErrorRecords); SAFE_RELEASE(pISupportErrorInfo); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IDBCreateCommand // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_IDBCreateCommand(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables IUnknown* pIUnknown = NULL; ThreadSwitch(); //Let the other thread(s) catch up //Provider might not support CommandObjects if(pThis->GetCommandSupport()) { for(ULONG i=0; im_pIDBCreateCommand->CreateCommand(NULL,IID_ICommand,&pIUnknown),S_OK) SAFE_RELEASE(pIUnknown); } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIUnknown); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IDBCreateSession // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_IDBCreateSession(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; HRESULT hrExpected = (HRESULT)THREAD_ARG1; ASSERT(pThis); //Local Variables IUnknown* pIUnknown = NULL; IDBCreateSession* pIDBCreateSession = NULL; ULONG i=0; TESTC_(hr = QI(pThis->m_pIDBInitialize,IID_IDBCreateSession,(void**)&pIDBCreateSession),S_OK) ThreadSwitch(); //Let the other thread(s) catch up for(i=0; iCreateSession(NULL,IID_IOpenRowset,&pIUnknown),S_OK,hrExpected) SAFE_RELEASE(pIUnknown); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIDBCreateSession); SAFE_RELEASE(pIUnknown); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - Session (IDBTableDefinition) // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_IDBCreateTable(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables ITableDefinition* pITableDefinition = NULL; CTable* pTable = pThis->m_pTable; //TODO V2, QI fails with E_NOINTERFACE TESTC_(hr = QI(pThis->pISession(),IID_ITableDefinition,(void**)&pITableDefinition),S_OK) ThreadSwitch(); //Let the other thread(s) catch up //TESTC_(pITableDefinition->CreateTable(NULL, &pTable->GetTableID(), pTable->CountColumnsOnTable(), m_rgColumnDescs, IID_IRowset, NULL, NULL),S_OK) ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pITableDefinition); THREAD_END(hr); } ULONG CThreads::Thread_AddColumn(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables ITableDefinition* pITableDefinition = NULL; CTable* pTable = pThis->m_pTable; //TODO V2, QI Above fails with E_NOINTERFACE TESTC_(hr = QI(pThis->pISession(),IID_ITableDefinition,(void**)&pITableDefinition),S_OK) ThreadSwitch(); //Let the other thread(s) catch up TESTC_(hr = pITableDefinition->AddColumn(&pTable->GetTableID(), NULL, NULL),S_OK) ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pITableDefinition); THREAD_END(hr); } ULONG CThreads::Thread_DropColumn(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables ITableDefinition* pITableDefinition = NULL; CTable* pTable = pThis->m_pTable; //TODO V2, QI fails with E_NOINTERFACE TESTC_(hr = QI(pThis->pISession(),IID_ITableDefinition,(void**)&pITableDefinition),S_OK) ThreadSwitch(); //Let the other thread(s) catch up TESTC_(hr = pITableDefinition->AddColumn(&pTable->GetTableID(), NULL, NULL),S_OK) ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pITableDefinition); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - Schema // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_GetSchemaRowset(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables IDBSchemaRowset* pIDBSchemaRowset = NULL; IUnknown* pIUnknown = NULL; ULONG i=0; ThreadSwitch(); //Let the other thread(s) catch up //IDBSchemaRowset is optional TESTC_PROVIDER(hr = QI(pThis->pISession(),IID_IDBSchemaRowset,(void**)&pIDBSchemaRowset)==S_OK); for(i=0; iGetRowset(NULL,DBSCHEMA_PROVIDER_TYPES,0,NULL,IID_IRowset,0,NULL,&pIUnknown),S_OK); SAFE_RELEASE(pIUnknown); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIDBSchemaRowset); SAFE_RELEASE(pIUnknown); THREAD_END(hr); } ULONG CThreads::Thread_GetSchemaInfo(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables IDBSchemaRowset* pIDBSchemaRowset = NULL; ULONG i,cSchemas = 0; GUID* rgSchemas = NULL; ULONG* rgRestrictions = NULL; ThreadSwitch(); //Let the other thread(s) catch up //IDBSchemaRowset is optional TESTC_PROVIDER(hr = QI(pThis->pISession(),IID_IDBSchemaRowset,(void**)&pIDBSchemaRowset)==S_OK); for(i=0; iGetSchemas(&cSchemas,&rgSchemas,&rgRestrictions),S_OK) PROVIDER_FREE(rgSchemas); PROVIDER_FREE(rgRestrictions); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIDBSchemaRowset); PROVIDER_FREE(rgSchemas); PROVIDER_FREE(rgRestrictions); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - ClassFactory // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_GetClassFactory(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables IClassFactory* pIClassFactory = NULL; ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; iCreateInstance(NULL,IID_IDBInitialize,(void**)&pIDBInitialize), S_OK); SAFE_RELEASE(pIDBInitialize); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIDBInitialize); THREAD_END(hr); } ULONG CThreads::Thread_PersistFileSave(LPVOID pv) { THREAD_BEGIN HRESULT hr = NOERROR; //Thread Stack Variables IDBInitialize* pThis = (IDBInitialize*)THREAD_FUNC; ASSERT(pThis); //Local Variables IPersistFile* pIPersistFile = NULL; hr=QI(pThis,IID_IPersistFile,(void**)&pIPersistFile); TEST2C_(hr, S_OK, E_NOINTERFACE); ThreadSwitch(); //Let the other thread(s) catch up if(pIPersistFile) { for(ULONG i=0; iSave(PERSIST_FILE, FALSE),S_OK) } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIPersistFile); THREAD_END(hr); } ULONG CThreads::Thread_PersistFileLoad(LPVOID pv) { THREAD_BEGIN HRESULT hr = NOERROR; //Thread Stack Variables IDBInitialize* pThis = (IDBInitialize*)THREAD_FUNC; ASSERT(pThis); //Local Variables IPersistFile* pIPersistFile = NULL; TEST2C_(hr=QI(pThis,IID_IPersistFile,(void**)&pIPersistFile), S_OK, E_NOINTERFACE); ThreadSwitch(); //Let the other thread(s) catch up if(pIPersistFile) { for(ULONG i=0; iLoad(PERSIST_FILE, 0),S_OK) } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIPersistFile); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IConnectionPoint // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_CreateListener(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables IConnectionPoint* pICP = NULL; IConnectionPointContainer* pICPC = NULL; DWORD dwCookie = 0; ULONG i=0; //Instantiate a listener object, within this thread CListener* pCListener = new CListener(IID_IRowsetNotify, pThis->pIRowset()); TESTC(pCListener!=NULL); pCListener->AddRef(); //Obtain the connection point container TESTC_(hr = pThis->pIRowset()->QueryInterface(IID_IConnectionPointContainer,(void **)&pICPC),S_OK) //Obtain the IRowsetNotify connection point TESTC_(hr = pICPC->FindConnectionPoint(IID_IRowsetNotify,&pICP),S_OK) //Now we can advise the connection from the rowset->pICP to the listener in this thread TESTC_(hr = pICP->Advise(pCListener,&dwCookie),S_OK) ThreadSwitch(); //Let the other thread(s) catch up //We need to stall, so that we give enough time for the rowset in the main //thread to generate a notification, so that we pick it up before //closing/unadvising this connection //Wait until where notified from the Rowset //But don't get caught in a infinite loop for(i=0; i<10; i++) { if(pCListener->GetTimesNotified() > 0) break; SleepEx(1000,FALSE); } //Make sure that we are notified once and only once TESTC(pCListener->GetTimesNotified() > 0) CLEANUP: //Unadvise the connection to the listener if(pICP) pICP->Unadvise(dwCookie); SAFE_RELEASE(pCListener); SAFE_RELEASE(pICP); SAFE_RELEASE(pICPC); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - ITransaction // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_StartTransaction(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables ThreadSwitch(); //Let the other thread(s) catch up //TODO ThreadSwitch(); //Let the other thread(s) catch up THREAD_END(hr); } ULONG CThreads::Thread_Commit(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables ThreadSwitch(); //Let the other thread(s) catch up //TODO ThreadSwitch(); //Let the other thread(s) catch up THREAD_END(hr); } ULONG CThreads::Thread_Abort(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables ThreadSwitch(); //Let the other thread(s) catch up //TODO ThreadSwitch(); //Let the other thread(s) catch up THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IRowset // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_AddRefRows(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; HROW* pHROW = (HROW*)THREAD_ARG1; ASSERT(pThis && pHROW); ThreadSwitch(); //Let the other thread(s) catch up TESTC_(hr = pThis->pIRowset()->AddRefRows(ONE_ROW,pHROW,NULL,NULL),S_OK) ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_END(hr); } ULONG CThreads::Thread_ReleaseRows(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; HROW* pHROW = (HROW*)THREAD_ARG1; HRESULT hrExpected= (HRESULT)THREAD_ARG2; ASSERT(pThis && pHROW); ThreadSwitch(); //Let the other thread(s) catch up TEST2C_(hr = pThis->pIRowset()->ReleaseRows(ONE_ROW,pHROW,NULL,NULL,NULL),S_OK,hrExpected); ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_END(hr); } ULONG CThreads::Thread_GetNextRows(LPVOID pv) { THREAD_BEGIN //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; DBROWCOUNT lOffset = (LONG)THREAD_ARG1; DBROWCOUNT cRows = (LONG)THREAD_ARG2; HRESULT hrExpected= (HRESULT)THREAD_ARG3; HRESULT hr = S_OK; ASSERT(pThis); //Local Variables DBCOUNTITEM cRowsObtained = 0; HROW* rghRow = NULL; ThreadSwitch(); //Let the other thread(s) catch up //MAXOPENROWS if(pThis->m_ulMaxOpenRows!=0 && (ULONG)cRows>pThis->m_ulMaxOpenRows) cRows = pThis->m_ulMaxOpenRows; //GetNextRows may return DB_E_BADSTARTPOSITION if the row //that currently marks the next fecth position is deleted. Therefore //the Arg passed into this func will let us know if there might be a possibility //of a DeleteRows while this thread is executing... TEST2C_(hr = pThis->pIRowset()->GetNextRows(NULL, lOffset, cRows, &cRowsObtained, &rghRow), S_OK, hrExpected); if(hr==S_OK) { //Verify results TESTC(cRowsObtained==(ULONG)cRows && rghRow!=NULL) } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->pIRowset()->ReleaseRows(cRowsObtained,rghRow,NULL,NULL,NULL); PROVIDER_FREE(rghRow); THREAD_END(hr); } ULONG CThreads::Thread_GetData(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; ASSERT(THREAD_FUNC); //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ULONG cRows = (ULONG)THREAD_ARG1; HROW* rghRows = (HROW*)THREAD_ARG2; HACCESSOR hAccessor = *(HACCESSOR*)THREAD_ARG3; HRESULT hrExpected = (HRESULT)THREAD_ARG4; //Allocate Data void* pData = PROVIDER_ALLOC(pThis->m_cRowSize * sizeof(void*)); ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; ipIRowset()->GetData(rghRows[iRow], hAccessor, pData); if(FAILED(hr) && hrExpected == DB_E_DELETEDROW) { //According to the spec its provider specific if GetData is passed //a deleted row, but it cannot terminate abormally. Anyother problem //such as an invalid row it can crash, but not for deleted. The reason //is that many provider will can REMOVEDELETED = FALSE, then when //looping through the rowset there will be deleted rows... //We will issue a warning if something other than the obvious DB_E_DELETEDROW CHECKW(hr, DB_E_DELETEDROW); } else { TEST2C_(hr, S_OK, hrExpected); } pThis->ReleaseRowData(pData, hAccessor, FALSE); //Only free outofline, don't free the actual buffer... } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->ReleaseRowData(pData, hAccessor); THREAD_END(hr); } ULONG CThreads::Thread_RestartPosition(LPVOID pv) { THREAD_BEGIN //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ULONG fRowsReleased = (ULONG)THREAD_ARG1; ASSERT(pThis && (fRowsReleased == TRUE || fRowsReleased == FALSE)); HRESULT hr = S_OK; ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; ipIRowset()->RestartPosition(NULL); //Verify Results if(fRowsReleased || SUCCEEDED(hr)) { TEST2C_(hr, S_OK, DB_S_COMMANDREEXECUTED); } else { //According to the 2.0 OLE DB Spec, some providers may not be able to //RestartPosition when there are Rows currently held, (even with CANHOLDROWS) TESTC_(hr,DB_E_ROWSNOTRELEASED); //But there are some restrictions. (and you thought it was going to be easy) //DBPROP_QUICKRESTART must also be FALSE TESTC(pThis->GetProperty(DBPROP_QUICKRESTART, DBPROPSET_ROWSET, VARIANT_FALSE)); } } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IOpenRowset // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_OpenRowset(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Obtain thread stack variables COpenRowset* pThis = (COpenRowset*)THREAD_FUNC; ULONG cPropSets = (ULONG)THREAD_ARG1; DBPROPSET* rgPropSets = (DBPROPSET*)THREAD_ARG2; ASSERT(pThis); //Local Variables IRowset* pIRowset = NULL; ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; ipIOpenRowset()->OpenRowset(NULL,&pThis->m_pTable->GetTableID(),NULL,IID_IRowset,cPropSets,rgPropSets,(IUnknown**)&pIRowset),S_OK) SAFE_RELEASE(pIRowset); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIRowset); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IRowsetChange // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_SetData(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowsetChange* pThis = (CRowsetChange*)THREAD_FUNC; HROW* phRow = (HROW*)THREAD_ARG1; HACCESSOR* phAccessor = (HACCESSOR*)THREAD_ARG2; HRESULT hrExpected = (HRESULT)THREAD_ARG3; ASSERT(pThis && phRow && phAccessor); void* pData = NULL; ThreadSwitch(); //Let the other thread(s) catch up //Could be called while a ReleaseRows is called for(ULONG i=0; iMakeRowData(&pData, *phAccessor); //Set data TEST2C_(hr = pThis->SetData(*phRow, *phAccessor, pData), S_OK, hrExpected); //Only Release out-of-line data, not the buffer pThis->ReleaseRowData(pData, *phAccessor, FALSE); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->ReleaseRowData(pData, *phAccessor); THREAD_END(hr); } ULONG CThreads::Thread_DeleteRows(LPVOID pv) { THREAD_BEGIN HRESULT hr; //Thread Stack Variables CRowsetChange* pThis = (CRowsetChange*)THREAD_FUNC; ULONG cRows = (ULONG)THREAD_ARG1; HROW* rghRow = (HROW*)THREAD_ARG2; HRESULT hrExpected = (HRESULT)THREAD_ARG3; HRESULT hrExpected2 = (HRESULT)THREAD_ARG4; ASSERT(pThis && cRows && rghRow); //Local Variables DBROWSTATUS* rgRowStatus = (DBROWSTATUS*)PROVIDER_ALLOC(cRows*sizeof(DBROWSTATUS)); ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; ipIRowsetChange()->DeleteRows(NULL,cRows,rghRow,rgRowStatus); TEST3C_(hr, S_OK, hrExpected, hrExpected2) if(hr==S_OK) { TESTC(VerifyArray(cRows, rgRowStatus, DBROWSTATUS_S_OK)); } else { //make sure that any error was due to other threads interactions //it may have already been deleted or released by another thread for(ULONG iStatus=0; iStatusMakeRowData(&pData, *phAccessor); TEST2C_(hr = pThis->pIRowsetChange()->InsertRow(NULL, *phAccessor, pData, &rghRows[i]),S_OK,hrExpected) pThis->ReleaseRowData(pData, *phAccessor); pData = NULL; } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->pIRowset()->ReleaseRows(MAX_ITERATIONS, rghRows, NULL, NULL, NULL); pThis->ReleaseRowData(pData, *phAccessor); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IRowsetInfo // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_GetRowsetProperties(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ULONG cPropIDSets = (ULONG)THREAD_ARG1; DBPROPIDSET* rgPropIDSets = (DBPROPIDSET*)THREAD_ARG2; ASSERT(pThis); //Can be (NULL) for all supported properties //Local Variables ULONG i,cPropSets = 0; DBPROPSET* rgPropSets = NULL; IRowsetInfo* pIRowsetInfo = NULL; TESTC_(hr = QI(pThis->pIRowset(),IID_IRowsetInfo,(void**)&pIRowsetInfo),S_OK) ThreadSwitch(); //Let the other thread(s) catch up for(i=0; iGetProperties(cPropIDSets, rgPropIDSets, &cPropSets, &rgPropSets),S_OK); TESTC(rgPropSets!=NULL); ::FreeProperties(&cPropSets,&rgPropSets); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIRowsetInfo); ::FreeProperties(&cPropSets,&rgPropSets); THREAD_END(hr); } ULONG CThreads::Thread_GetSpecification(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; IID* priid = (IID*)THREAD_ARG1; ASSERT(pThis && priid); ULONG i=0; //Local Variables IUnknown* pIUnknown = NULL; IRowsetInfo* pIRowsetInfo = NULL; TESTC_(QI(pThis->pIRowset(),IID_IRowsetInfo,(void**)&pIRowsetInfo),S_OK) ThreadSwitch(); //Let the other thread(s) catch up for(i=0; iGetSpecification(*priid,&pIUnknown); TEST2C_(hr,S_OK,S_FALSE); if(hr==S_OK) { TESTC(pIUnknown!=NULL); } else { TWARNING("GetSpecification returned S_FALSE?"); TESTC(pIUnknown==NULL); } SAFE_RELEASE(pIUnknown); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIUnknown); SAFE_RELEASE(pIRowsetInfo); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IRowsetResynch // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_GetVisibleData(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; HROW* phRow = (HROW*)THREAD_ARG1; HACCESSOR* phAccessor = (HACCESSOR*)THREAD_ARG2; ASSERT(pThis && phRow && phAccessor); //Allocate Data void* pData = PROVIDER_ALLOC((sizeof(void*)*pThis->m_cRowSize)); ULONG i=0; //Local Variables IRowsetResynch* pIRowsetResynch = NULL; TESTC_(hr = QI(pThis->pIRowset(),IID_IRowsetResynch,(void**)&pIRowsetResynch),S_OK) ThreadSwitch(); //Let the other thread(s) catch up for(i=0; iGetVisibleData(*phRow,*phAccessor, pData),S_OK) pThis->ReleaseRowData(pData, *phAccessor,FALSE); //Only release the out-of-line memory } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: SAFE_RELEASE(pIRowsetResynch); pThis->ReleaseRowData(pData, *phAccessor); THREAD_END(hr); } ULONG CThreads::Thread_ResynchRows(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables DBCOUNTITEM i,cRowsResynched = 0; HROW* rghRowsResynched = NULL; DBROWSTATUS* rgRowStatus = NULL; //Local Variables IRowsetResynch* pIRowsetResynch = NULL; TESTC_(QI(pThis->pIRowset(),IID_IRowsetResynch,(void**)&pIRowsetResynch),S_OK) ThreadSwitch(); //Let the other thread(s) catch up //Resynch all rows //Can return DB_S_ for rows not resycned (unchanged) for(i=0; iResynchRows(0,NULL,&cRowsResynched,&rghRowsResynched,&rgRowStatus); TEST2C_(hr, S_OK, DB_S_ERRORSOCCURRED) pThis->pIRowset()->ReleaseRows(cRowsResynched,rghRowsResynched,NULL,NULL,NULL); PROVIDER_FREE(rghRowsResynched); PROVIDER_FREE(rgRowStatus); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->pIRowset()->ReleaseRows(cRowsResynched,rghRowsResynched,NULL,NULL,NULL); PROVIDER_FREE(rghRowsResynched); PROVIDER_FREE(rgRowStatus); SAFE_RELEASE(pIRowsetResynch); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IRowsetWithParameters // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_Requery(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); ThreadSwitch(); //Let the other thread(s) catch up //TODO V2 ThreadSwitch(); //Let the other thread(s) catch up THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IRowsetLocate // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_GetRowsAt(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; ASSERT(pThis); //Local Variables IRowsetLocate* pIRowsetLocate = NULL; DBCOUNTITEM i,cRowsObtained = 0; HROW* rghRow = NULL; BYTE Bookmark = DBBMK_FIRST; TESTC_(hr = QI(pThis->pIRowset(),IID_IRowsetLocate,(void**)&pIRowsetLocate),S_OK) ThreadSwitch(); //Let the other thread(s) catch up for(i=0; iGetRowsAt(NULL,NULL,1,&Bookmark,0, ONE_ROW, &cRowsObtained, &rghRow),S_OK) pThis->pIRowset()->ReleaseRows(cRowsObtained,rghRow,NULL,NULL,NULL); PROVIDER_FREE(rghRow); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->pIRowset()->ReleaseRows(cRowsObtained,rghRow,NULL,NULL,NULL); PROVIDER_FREE(rghRow); SAFE_RELEASE(pIRowsetLocate); THREAD_END(hr); } ULONG CThreads::Thread_GetRowsByBookmark(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; DBBKMARK* pcbBookmark = (DBBKMARK*)THREAD_ARG1; BYTE** ppBookmark = (BYTE**)THREAD_ARG2; ASSERT(pThis && pcbBookmark && ppBookmark); //Local Variables IRowsetLocate* pIRowsetLocate = NULL; HROW rghRows[MAX_ITERATIONS]; DBROWSTATUS rgRowStatus[ONE_ROW]; const BYTE* rgpBookmark[] = {*ppBookmark}; ULONG i=0; //Obtain the Locate interface TESTC_(hr = QI(pThis->pIRowset(),IID_IRowsetLocate,(void**)&pIRowsetLocate),S_OK) ThreadSwitch(); //Let the other thread(s) catch up //GetRowsByBookmark for(i=0; iGetRowsByBookmark(NULL, ONE_ROW, pcbBookmark, rgpBookmark, &rghRows[i], rgRowStatus),S_OK) } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->pIRowset()->ReleaseRows(MAX_ITERATIONS, rghRows, NULL, NULL, NULL); SAFE_RELEASE(pIRowsetLocate); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IRowsetUpdate // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_GetOriginalData(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowsetUpdate* pThis = (CRowsetUpdate*)THREAD_FUNC; HROW* phRow = (HROW*)THREAD_ARG1; HACCESSOR* phAccessor = (HACCESSOR*)THREAD_ARG2; ASSERT(pThis && phRow && phAccessor); //Allocate Data void* pData = PROVIDER_ALLOC((sizeof(void*)*pThis->m_cRowSize)); ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; ipIRowsetUpdate()->GetOriginalData(*phRow,*phAccessor, pData),S_OK) pThis->ReleaseRowData(pData, *phAccessor,FALSE);//Only free the out-of-line memory, not the buffer } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->ReleaseRowData(pData, *phAccessor); THREAD_END(hr); } ULONG CThreads::Thread_GetPendingRows(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowsetUpdate* pThis = (CRowsetUpdate*)THREAD_FUNC; ASSERT(pThis); //Local Variables DBCOUNTITEM cPendingRows = 0; HROW* rgPendingRows = NULL; DBROWSTATUS* rgPendingStatus = NULL; ThreadSwitch(); //Let the other thread(s) catch up //GetPendingRows for all rows //Can be either S_OK (pending rows) or S_FALSE (no pending rows) for(ULONG i=0; ipIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&rgPendingStatus); TEST2C_(hr, S_OK, S_FALSE); pThis->pIRowset()->ReleaseRows(cPendingRows,rgPendingRows,NULL,NULL,NULL); PROVIDER_FREE(rgPendingRows); PROVIDER_FREE(rgPendingStatus); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->pIRowset()->ReleaseRows(cPendingRows,rgPendingRows,NULL,NULL,NULL); PROVIDER_FREE(rgPendingRows); PROVIDER_FREE(rgPendingStatus); THREAD_END(hr); } ULONG CThreads::Thread_GetRowStatus(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowsetUpdate* pThis = (CRowsetUpdate*)THREAD_FUNC; ULONG* pcRows = (ULONG*)THREAD_ARG1; HROW* rghRow = (HROW*)THREAD_ARG2; HRESULT hrExpected = (HRESULT)THREAD_ARG3; HRESULT hrExpected2 = (HRESULT)THREAD_ARG3; ASSERT(pThis && pcRows && rghRow); //Local Variables DBROWSTATUS* rgPendingStatus = (DBROWSTATUS*)PROVIDER_ALLOC(sizeof(DBROWSTATUS)*(*pcRows)); ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; ipIRowsetUpdate()->GetRowStatus(NULL,*pcRows,rghRow,rgPendingStatus); TEST3C_(hr, S_OK, hrExpected, hrExpected2); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: PROVIDER_FREE(rgPendingStatus); THREAD_END(hr); } ULONG CThreads::Thread_Undo(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowsetUpdate* pThis = (CRowsetUpdate*)THREAD_FUNC; ASSERT(pThis); //Local Variables DBCOUNTITEM cRowsUndone = 0; HROW* rgRowsUndone = NULL; DBROWSTATUS* rgRowStatus = NULL; ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; ipIRowsetUpdate()->Undo(NULL,0,NULL,&cRowsUndone,&rgRowsUndone,&rgRowStatus),S_OK) pThis->pIRowset()->ReleaseRows(cRowsUndone,rgRowsUndone,NULL,NULL,NULL); PROVIDER_FREE(rgRowsUndone); PROVIDER_FREE(rgRowStatus); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->pIRowset()->ReleaseRows(cRowsUndone,rgRowsUndone,NULL,NULL,NULL); PROVIDER_FREE(rgRowsUndone); PROVIDER_FREE(rgRowStatus); THREAD_END(hr); } ULONG CThreads::Thread_Update(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowsetUpdate* pThis = (CRowsetUpdate*)THREAD_FUNC; ASSERT(pThis); //Local Variables DBCOUNTITEM cUpdatedRows = 0; HROW* rgUpdatedRows = NULL; DBROWSTATUS* rgRowStatus = NULL; ThreadSwitch(); //Let the other thread(s) catch up for(ULONG i=0; ipIRowsetUpdate()->Update(NULL,0,NULL,&cUpdatedRows,&rgUpdatedRows,&rgRowStatus),S_OK) pThis->pIRowset()->ReleaseRows(cUpdatedRows,rgUpdatedRows,NULL,NULL,NULL); PROVIDER_FREE(rgUpdatedRows); PROVIDER_FREE(rgRowStatus); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: pThis->pIRowset()->ReleaseRows(cUpdatedRows,rgUpdatedRows,NULL,NULL,NULL); PROVIDER_FREE(rgUpdatedRows); PROVIDER_FREE(rgRowStatus); THREAD_END(hr); } /////////////////////////////////////////////////////////// // Thread routines - IMultipleResults // /////////////////////////////////////////////////////////// ULONG CThreads::Thread_GetResult(LPVOID pv) { THREAD_BEGIN HRESULT hr = S_OK; //Thread Stack Variables CRowset* pThis = (CRowset*)THREAD_FUNC; //[in] IMultipleResults* pIMultipleResults = (IMultipleResults*)THREAD_ARG1; //[in] IRowset** ppIRowset = (IRowset**)THREAD_ARG2; //[out] ASSERT(pThis && pIMultipleResults && ppIRowset); ThreadSwitch(); //Let the other thread(s) catch up //IMultipleResults::GetResults can return S_OK or DB_E_NORESULT if already //processed all the result sets hr = pIMultipleResults->GetResult(NULL, 0, IID_IRowset, NULL, (IUnknown**)ppIRowset); TEST3C_(hr, S_OK, DB_E_OBJECTOPEN, DB_S_NORESULT); //Verify Results if(hr == S_OK) { TESTC(*ppIRowset != NULL); } else { TESTC(*ppIRowset == NULL); } ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_END(hr); } // {{ TCW_TEST_CASE_MAP(TCDataSource) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the DataSourceObject // class TCDataSource : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCDataSource,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember GetDataSource threading model CLSID int Variation_1(); // @cmember GetProperties and SetProperites on the same DSO int Variation_2(); // @cmember GetProperties on the same set of properties int Variation_3(); // @cmember GetPropertyInfo on all properties supported int Variation_4(); // @cmember SetProperties on the same DSO int Variation_5(); // @cmember Initialize the DSO from sep threads int Variation_6(); // @cmember Unitilize the DSO from sep threads int Variation_7(); // @cmember Initialize / Unitialize same DSO from sep threads int Variation_8(); // @cmember Initialize seperate DSOs in threads int Variation_9(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCDataSource) #define THE_CLASS TCDataSource BEG_TEST_CASE(TCDataSource, CThreads, L"Multi-Threaded testing of the DataSourceObject") TEST_VARIATION(1, L"GetDataSource threading model CLSID") TEST_VARIATION(2, L"GetProperties and SetProperites on the same DSO") TEST_VARIATION(3, L"GetProperties on the same set of properties") TEST_VARIATION(4, L"GetPropertyInfo on all properties supported") TEST_VARIATION(5, L"SetProperties on the same DSO") TEST_VARIATION(6, L"Initialize the DSO from sep threads") TEST_VARIATION(7, L"Unitilize the DSO from sep threads") TEST_VARIATION(8, L"Initialize / Unitialize same DSO from sep threads") TEST_VARIATION(9, L"Initialize seperate DSOs in threads") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCSession) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the SessionObject // class TCSession : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCSession,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Get the Session Threading model CLSID int Variation_1(); // @cmember Get the Session threading model Property int Variation_2(); // @cmember CreateSession from sep threads int Variation_3(); // @cmember CreateCommand from seperate threads int Variation_4(); // @cmember Empty int Variation_5(); // @cmember Add a column / drop a column from sep threads int Variation_6(); // @cmember Create a table from seperate threads int Variation_7(); // @cmember Empty int Variation_8(); // @cmember Get schema rowset from seperate threads int Variation_9(); // @cmember Get schema info from sep threads int Variation_10(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCSession) #define THE_CLASS TCSession BEG_TEST_CASE(TCSession, CThreads, L"Multi-Threaded testing of the SessionObject") TEST_VARIATION(1, L"Get the Session Threading model CLSID") TEST_VARIATION(2, L"Get the Session threading model Property") TEST_VARIATION(3, L"CreateSession from sep threads") TEST_VARIATION(4, L"CreateCommand from seperate threads") TEST_VARIATION(5, L"Empty") TEST_VARIATION(6, L"Add a column / drop a column from sep threads") TEST_VARIATION(7, L"Create a table from seperate threads") TEST_VARIATION(8, L"Empty") TEST_VARIATION(9, L"Get schema rowset from seperate threads") TEST_VARIATION(10, L"Get schema info from sep threads") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCCommand) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the CommandObject // class TCCommand : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCCommand,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Get the command threading model CLSID int Variation_1(); // @cmember Get the command threading model Property int Variation_2(); // @cmember Create command objects on seperate threads int Variation_3(); // @cmember Call execute from sep threads, (same command object int Variation_4(); // @cmember Call cancel while two executes are occurring int Variation_5(); // @cmember Empty int Variation_6(); // @cmember Set/Unset diff prop int Variation_7(); // @cmember Set/Unset same prop int Variation_8(); // @cmember Get/Set prop from sep threads int Variation_9(); // @cmember Set the command text / Get text from another thread int Variation_10(); // @cmember Empty int Variation_11(); // @cmember Uprepare / Prepare int Variation_12(); // @cmember Unprepare / Execute int Variation_13(); // @cmember Empty int Variation_14(); // @cmember SetDefaultValues from sep threads, GetDefaultValues from a third int Variation_15(); // @cmember Empty int Variation_16(); // @cmember Execute / Release the command object int Variation_17(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCCommand) #define THE_CLASS TCCommand BEG_TEST_CASE(TCCommand, CThreads, L"Multi-Threaded testing of the CommandObject") TEST_VARIATION(1, L"Get the command threading model CLSID") TEST_VARIATION(2, L"Get the command threading model Property") TEST_VARIATION(3, L"Create command objects on seperate threads") TEST_VARIATION(4, L"Call execute from sep threads, (same command object") TEST_VARIATION(5, L"Call cancel while two executes are occurring") TEST_VARIATION(6, L"Empty") TEST_VARIATION(7, L"Set/Unset diff prop") TEST_VARIATION(8, L"Set/Unset same prop") TEST_VARIATION(9, L"Get/Set prop from sep threads") TEST_VARIATION(10, L"Set the command text / Get text from another thread") TEST_VARIATION(11, L"Empty") TEST_VARIATION(12, L"Uprepare / Prepare") TEST_VARIATION(13, L"Unprepare / Execute") TEST_VARIATION(14, L"Empty") TEST_VARIATION(15, L"SetDefaultValues from sep threads, GetDefaultValues from a third") TEST_VARIATION(16, L"Empty") TEST_VARIATION(17, L"Execute / Release the command object") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCAccessor) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the Accessor object // class TCAccessor : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCAccessor,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Create multiple accessors from diff threads int Variation_1(); // @cmember Use the same accessor on diff threads int Variation_2(); // @cmember Empty int Variation_3(); // @cmember GetBindiings / ReleaseAcessor int Variation_4(); // @cmember GetColumnsInfo / IRowsetInfo int Variation_5(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCAccessor) #define THE_CLASS TCAccessor BEG_TEST_CASE(TCAccessor, CThreads, L"Multi-Threaded testing of the Accessor object") TEST_VARIATION(1, L"Create multiple accessors from diff threads") TEST_VARIATION(2, L"Use the same accessor on diff threads") TEST_VARIATION(3, L"Empty") TEST_VARIATION(4, L"GetBindiings / ReleaseAcessor") TEST_VARIATION(5, L"GetColumnsInfo / IRowsetInfo") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCError) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the ErrorObject // class TCError : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCError,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Get the Error object threading model CLSID int Variation_1(); // @cmember Get the Error object threading model Property int Variation_2(); // @cmember AddErrorRecord from sep threads, GetErrorInfo from a third int Variation_3(); // @cmember Transfer error record to antoher thread. int Variation_4(); // @cmember Apartment model - make sure apartment model error object is returned int Variation_5(); // @cmember Empty int Variation_6(); // @cmember Generate Errors from sep threads int Variation_7(); // @cmember Use diff threads to make IErrorInfo calls int Variation_8(); // @cmember Create Error object on 1 thread, set error info from many other threads int Variation_9(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCError) #define THE_CLASS TCError BEG_TEST_CASE(TCError, CThreads, L"Multi-Threaded testing of the ErrorObject") TEST_VARIATION(1, L"Get the Error object threading model CLSID") TEST_VARIATION(2, L"Get the Error object threading model Property") TEST_VARIATION(3, L"AddErrorRecord from sep threads, GetErrorInfo from a third") TEST_VARIATION(4, L"Transfer error record to antoher thread.") TEST_VARIATION(5, L"Apartment model - make sure apartment model error object is returned") TEST_VARIATION(6, L"Empty") TEST_VARIATION(7, L"Generate Errors from sep threads") TEST_VARIATION(8, L"Use diff threads to make IErrorInfo calls") TEST_VARIATION(9, L"Create Error object on 1 thread, set error info from many other threads") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCTransaction) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the TransactionObject // class TCTransaction : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCTransaction,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Get the transaction threading model CLSID int Variation_1(); // @cmember Get the transaction threading model Property int Variation_2(); // @cmember Two Commits, from two transactions int Variation_3(); // @cmember Multiple thread running under one transaction, commit int Variation_4(); // @cmember Multiple thread running under one transaction, abort int Variation_5(); // @cmember Empty int Variation_6(); // @cmember One thread aborts, while the other is doing real work int Variation_7(); // @cmember One thread commits, while the other thread is doing real work int Variation_8(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCTransaction) #define THE_CLASS TCTransaction BEG_TEST_CASE(TCTransaction, CThreads, L"Multi-Threaded testing of the TransactionObject") TEST_VARIATION(1, L"Get the transaction threading model CLSID") TEST_VARIATION(2, L"Get the transaction threading model Property") TEST_VARIATION(3, L"Two Commits, from two transactions") TEST_VARIATION(4, L"Multiple thread running under one transaction, commit") TEST_VARIATION(5, L"Multiple thread running under one transaction, abort") TEST_VARIATION(6, L"Empty") TEST_VARIATION(7, L"One thread aborts, while the other is doing real work") TEST_VARIATION(8, L"One thread commits, while the other thread is doing real work") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCOpenRowset) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the OpenRowsetObject // class TCOpenRowset : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCOpenRowset,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember QI for IID_IOpenRowset from sep threads int Variation_1(); // @cmember Call OpenRowset from two threads, diff prop, from the same table int Variation_2(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCOpenRowset) #define THE_CLASS TCOpenRowset BEG_TEST_CASE(TCOpenRowset, CThreads, L"Multi-Threaded testing of the OpenRowsetObject") TEST_VARIATION(1, L"QI for IID_IOpenRowset from sep threads") TEST_VARIATION(2, L"Call OpenRowset from two threads, diff prop, from the same table") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCRowset) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the RowsetObject // class TCRowset : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCRowset,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Empty int Variation_1(); // @cmember Verify threading model - Free Threaded int Variation_2(); // @cmember Verify read-only threading property int Variation_3(); // @cmember Empty int Variation_4(); // @cmember QI from sep threads for diff riid's int Variation_5(); // @cmember AddRef / Release testing int Variation_6(); // @cmember AddRefRows / ReleaseRows testing int Variation_7(); // @cmember Empty int Variation_8(); // @cmember GetNextRows from multiple threads int Variation_9(); // @cmember GetNextRows from multiple threads, with overlapping set of rows int Variation_10(); // @cmember GetNextRows and GetData from seperate threads int Variation_11(); // @cmember Empty int Variation_12(); // @cmember RestartPosition with GetNextRows int Variation_13(); // @cmember RestartPosition with GetData int Variation_14(); // @cmember Empty int Variation_15(); // @cmember Release a row being accessed by GetNextRows int Variation_16(); // @cmember Delete a row, being accessed by GetData int Variation_17(); // @cmember Release the rowset while being used by another int Variation_18(); // @cmember Empty int Variation_19(); // @cmember GetData, same row, same accessor, diff threads int Variation_20(); // @cmember GetData, same row, diff accessor, diff threads int Variation_21(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCRowset) #define THE_CLASS TCRowset BEG_TEST_CASE(TCRowset, CThreads, L"Multi-Threaded testing of the RowsetObject") TEST_VARIATION(1, L"Empty") TEST_VARIATION(2, L"Verify threading model - Free Threaded") TEST_VARIATION(3, L"Verify read-only threading property") TEST_VARIATION(4, L"Empty") TEST_VARIATION(5, L"QI from sep threads for diff riid's") TEST_VARIATION(6, L"AddRef / Release testing") TEST_VARIATION(7, L"AddRefRows / ReleaseRows testing") TEST_VARIATION(8, L"Empty") TEST_VARIATION(9, L"GetNextRows from multiple threads") TEST_VARIATION(10, L"GetNextRows from multiple threads, with overlapping set of rows") TEST_VARIATION(11, L"GetNextRows and GetData from seperate threads") TEST_VARIATION(12, L"Empty") TEST_VARIATION(13, L"RestartPosition with GetNextRows") TEST_VARIATION(14, L"RestartPosition with GetData") TEST_VARIATION(15, L"Empty") TEST_VARIATION(16, L"Release a row being accessed by GetNextRows") TEST_VARIATION(17, L"Delete a row, being accessed by GetData") TEST_VARIATION(18, L"Release the rowset while being used by another") TEST_VARIATION(19, L"Empty") TEST_VARIATION(20, L"GetData, same row, same accessor, diff threads") TEST_VARIATION(21, L"GetData, same row, diff accessor, diff threads") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCRowsetChange) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the RowsetChange Object // class TCRowsetChange : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCRowsetChange,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember SetData, diff columns, from seperate threads int Variation_1(); // @cmember SetData, same columns, from seperate threads int Variation_2(); // @cmember Empty int Variation_3(); // @cmember DeleteRows from seperate threads, with overlapping set of rows int Variation_4(); // @cmember Empty int Variation_5(); // @cmember Insert a row from seperate threads int Variation_6(); // @cmember Empty int Variation_7(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCRowsetChange) #define THE_CLASS TCRowsetChange BEG_TEST_CASE(TCRowsetChange, CThreads, L"Multi-Threaded testing of the RowsetChange Object") TEST_VARIATION(1, L"SetData, diff columns, from seperate threads") TEST_VARIATION(2, L"SetData, same columns, from seperate threads") TEST_VARIATION(3, L"Empty") TEST_VARIATION(4, L"DeleteRows from seperate threads, with overlapping set of rows") TEST_VARIATION(5, L"Empty") TEST_VARIATION(6, L"Insert a row from seperate threads") TEST_VARIATION(7, L"Empty") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCRowsetOther) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the other Rowset variants // class TCRowsetOther : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCRowsetOther,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember GetProperties from seperate threads int Variation_1(); // @cmember GetProperties while Releasing the Rowset int Variation_2(); // @cmember GetSpecification from seperate threads int Variation_3(); // @cmember Empty int Variation_4(); // @cmember Requery from seperate threads, V2 int Variation_5(); // @cmember Empty int Variation_6(); // @cmember GetRowsAt with a set of overlapping rows from seperate threads int Variation_7(); // @cmember GetRowsByBookmark with a set of overlapping rows from different threads int Variation_8(); // @cmember Empty int Variation_9(); // @cmember GetVisibleData while resyncing the rows int Variation_10(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCRowsetOther) #define THE_CLASS TCRowsetOther BEG_TEST_CASE(TCRowsetOther, CThreads, L"Multi-Threaded testing of the other Rowset variants") TEST_VARIATION(1, L"GetProperties from seperate threads") TEST_VARIATION(2, L"GetProperties while Releasing the Rowset") TEST_VARIATION(3, L"GetSpecification from seperate threads") TEST_VARIATION(4, L"Empty") TEST_VARIATION(5, L"Requery from seperate threads, V2") TEST_VARIATION(6, L"Empty") TEST_VARIATION(7, L"GetRowsAt with a set of overlapping rows from seperate threads") TEST_VARIATION(8, L"GetRowsByBookmark with a set of overlapping rows from different threads") TEST_VARIATION(9, L"Empty") TEST_VARIATION(10, L"GetVisibleData while resyncing the rows") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCRowsetUpdate) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the RowsetUpdate Object // class TCRowsetUpdate : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCRowsetUpdate,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Empty int Variation_1(); // @cmember Empty int Variation_2(); // @cmember Empty int Variation_3(); // @cmember GetPendingRows while GetRowStatus int Variation_4(); // @cmember GetPendingrows while Update int Variation_5(); // @cmember GetPendingRows while Undo int Variation_6(); // @cmember Empty int Variation_7(); // @cmember GetOriginalData while Update int Variation_8(); // @cmember GetOriginalData while GetVisibleData int Variation_9(); // @cmember Empty int Variation_10(); // @cmember Undo while Update int Variation_11(); // @cmember Empty int Variation_12(); // @cmember Insert while Update int Variation_13(); // @cmember Modify while Update int Variation_14(); // @cmember Delete while Update int Variation_15(); // @cmember Empty int Variation_16(); // @cmember Insert while Undo int Variation_17(); // @cmember Modify while Undo int Variation_18(); // @cmember Delete while Undo int Variation_19(); // @cmember Empty int Variation_20(); // @cmember Update while Resynch int Variation_21(); // @cmember Undo while Resynch int Variation_22(); // @cmember Empty int Variation_23(); // @cmember Requery while Updating int Variation_24(); // @cmember Requerying while Undo int Variation_25(); // @cmember Requery while GetOriginalData int Variation_26(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCRowsetUpdate) #define THE_CLASS TCRowsetUpdate BEG_TEST_CASE(TCRowsetUpdate, CThreads, L"Multi-Threaded testing of the RowsetUpdate Object") TEST_VARIATION(1, L"Empty") TEST_VARIATION(2, L"Empty") TEST_VARIATION(3, L"Empty") TEST_VARIATION(4, L"GetPendingRows while GetRowStatus") TEST_VARIATION(5, L"GetPendingrows while Update") TEST_VARIATION(6, L"GetPendingRows while Undo") TEST_VARIATION(7, L"Empty") TEST_VARIATION(8, L"GetOriginalData while Update") TEST_VARIATION(9, L"GetOriginalData while GetVisibleData") TEST_VARIATION(10, L"Empty") TEST_VARIATION(11, L"Undo while Update") TEST_VARIATION(12, L"Empty") TEST_VARIATION(13, L"Insert while Update") TEST_VARIATION(14, L"Modify while Update") TEST_VARIATION(15, L"Delete while Update") TEST_VARIATION(16, L"Empty") TEST_VARIATION(17, L"Insert while Undo") TEST_VARIATION(18, L"Modify while Undo") TEST_VARIATION(19, L"Delete while Undo") TEST_VARIATION(20, L"Empty") TEST_VARIATION(21, L"Update while Resynch") TEST_VARIATION(22, L"Undo while Resynch") TEST_VARIATION(23, L"Empty") TEST_VARIATION(24, L"Requery while Updating") TEST_VARIATION(25, L"Requerying while Undo") TEST_VARIATION(26, L"Requery while GetOriginalData") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCConnections) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the RowsetNotify and related Objects // class TCConnections : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCConnections,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Multiple Listeners on sep threads, ROW_ACTIVE sent to all threads on their own thread int Variation_1(); // @cmember Multiple Listeners on sep threads, GetNextRows / Modify - all notifcations go to all threads on their own thread int Variation_2(); // @cmember Empty int Variation_3(); // @cmember Multiple Listeners on sep threads, as well as the main thread being a listener int Variation_4(); // @cmember Empty int Variation_5(); // @cmember Two listeners on the same thread, as well as other single threaded listeners int Variation_6(); // @cmember Empty int Variation_7(); // @cmember All apartment model listeners int Variation_8(); // @cmember Some Apartment, Some Free-Threaded lsiteners int Variation_9(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCConnections) #define THE_CLASS TCConnections BEG_TEST_CASE(TCConnections, CThreads, L"Multi-Threaded testing of the RowsetNotify and related Objects") TEST_VARIATION(1, L"Multiple Listeners on sep threads, ROW_ACTIVE sent to all threads on their own thread") TEST_VARIATION(2, L"Multiple Listeners on sep threads, GetNextRows / Modify - all notifcations go to all threads on their own thread") TEST_VARIATION(3, L"Empty") TEST_VARIATION(4, L"Multiple Listeners on sep threads, as well as the main thread being a listener") TEST_VARIATION(5, L"Empty") TEST_VARIATION(6, L"Two listeners on the same thread, as well as other single threaded listeners") TEST_VARIATION(7, L"Empty") TEST_VARIATION(8, L"All apartment model listeners") TEST_VARIATION(9, L"Some Apartment, Some Free-Threaded lsiteners") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCSequence) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the various Rowset Objects together // class TCSequence : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCSequence,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember SetData multiple times int Variation_1(); // @cmember SetData for different columns within the same row int Variation_2(); // @cmember SetData and GetData for the same column/row int Variation_3(); // @cmember Empty int Variation_4(); // @cmember SetData and Resynch int Variation_5(); // @cmember GetData and Resynch int Variation_6(); // @cmember Empty int Variation_7(); // @cmember Insert a row while GetNextRows int Variation_8(); // @cmember Insert a row while GetData int Variation_9(); // @cmember Insert a row while DeleteRows int Variation_10(); // @cmember Empty int Variation_11(); // @cmember Modify a row while GetNextRows int Variation_12(); // @cmember Modify a row while GetData int Variation_13(); // @cmember Modify a row while ReleaseRows int Variation_14(); // @cmember Empty int Variation_15(); // @cmember Delete a row, while GetNextRows int Variation_16(); // @cmember Delete a row, while GetData int Variation_17(); // @cmember Delete a row, while SetData int Variation_18(); // @cmember Delete a row, while ReleaseRows int Variation_19(); // @cmember Empty int Variation_20(); // @cmember Requery while DeleteRows int Variation_21(); // @cmember Requery while Modifying and row int Variation_22(); // @cmember Requery while Inserting a row int Variation_23(); // @cmember Requery while GetNextRows int Variation_24(); // @cmember Requery while GetData int Variation_25(); // @cmember Requery while RestartPosition (causing a requery int Variation_26(); // @cmember Empty int Variation_27(); // @cmember GetNextRows while Locate int Variation_28(); // @cmember GetData while Locate int Variation_29(); // @cmember RestartPosition while Locate int Variation_30(); // @cmember Empty int Variation_31(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCSequence) #define THE_CLASS TCSequence BEG_TEST_CASE(TCSequence, CThreads, L"Multi-Threaded testing of the various Rowset Objects together") TEST_VARIATION(1, L"SetData multiple times") TEST_VARIATION(2, L"SetData for different columns within the same row") TEST_VARIATION(3, L"SetData and GetData for the same column/row") TEST_VARIATION(4, L"Empty") TEST_VARIATION(5, L"SetData and Resynch") TEST_VARIATION(6, L"GetData and Resynch") TEST_VARIATION(7, L"Empty") TEST_VARIATION(8, L"Insert a row while GetNextRows") TEST_VARIATION(9, L"Insert a row while GetData") TEST_VARIATION(10, L"Insert a row while DeleteRows") TEST_VARIATION(11, L"Empty") TEST_VARIATION(12, L"Modify a row while GetNextRows") TEST_VARIATION(13, L"Modify a row while GetData") TEST_VARIATION(14, L"Modify a row while ReleaseRows") TEST_VARIATION(15, L"Empty") TEST_VARIATION(16, L"Delete a row, while GetNextRows") TEST_VARIATION(17, L"Delete a row, while GetData") TEST_VARIATION(18, L"Delete a row, while SetData") TEST_VARIATION(19, L"Delete a row, while ReleaseRows") TEST_VARIATION(20, L"Empty") TEST_VARIATION(21, L"Requery while DeleteRows") TEST_VARIATION(22, L"Requery while Modifying and row") TEST_VARIATION(23, L"Requery while Inserting a row") TEST_VARIATION(24, L"Requery while GetNextRows") TEST_VARIATION(25, L"Requery while GetData") TEST_VARIATION(26, L"Requery while RestartPosition (causing a requery") TEST_VARIATION(27, L"Empty") TEST_VARIATION(28, L"GetNextRows while Locate") TEST_VARIATION(29, L"GetData while Locate") TEST_VARIATION(30, L"RestartPosition while Locate") TEST_VARIATION(31, L"Empty") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCClassFactory) //-------------------------------------------------------------------- // @class Multi-Threaded testing of the ClassFactory object // class TCClassFactory : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCClassFactory,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Call CoCreateobject instead of CoCreateInstance int Variation_1(); // @cmember Empty int Variation_2(); // @cmember PersistFile save, load from sep threads int Variation_3(); // @cmember Extended Error object int Variation_4(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCClassFactory) #define THE_CLASS TCClassFactory BEG_TEST_CASE(TCClassFactory, CThreads, L"Multi-Threaded testing of the ClassFactory object") TEST_VARIATION(1, L"Call CoCreateobject instead of CoCreateInstance") TEST_VARIATION(2, L"Empty") TEST_VARIATION(3, L"PersistFile save, load from sep threads") TEST_VARIATION(4, L"Extended Error object") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCRealWorld) //-------------------------------------------------------------------- // @class Real-World MultiThreaded senarios for OLEDB // class TCRealWorld : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCRealWorld,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Browser app, reading multiple columns concurrently int Variation_1(); // @cmember On-Line database int Variation_2(); // @cmember Multiple Querys on the same Connection Object int Variation_3(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCRealWorld) #define THE_CLASS TCRealWorld BEG_TEST_CASE(TCRealWorld, CThreads, L"Real-World MultiThreaded senarios for OLEDB") TEST_VARIATION(1, L"Browser app, reading multiple columns concurrently") TEST_VARIATION(2, L"On-Line database") TEST_VARIATION(3, L"Multiple Querys on the same Connection Object") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCMultipleResult) //-------------------------------------------------------------------- // @class Multi-Threaded testing for IMultipleResults // class TCMultipleResult : public CThreads { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCMultipleResult,CThreads); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember GetResults from seperate threads int Variation_1(); // }} TCW_TESTVARS_END }; // {{ TCW_TESTCASE(TCMultipleResult) #define THE_CLASS TCMultipleResult BEG_TEST_CASE(TCMultipleResult, CThreads, L"Multi-Threaded testing for IMultipleResults") TEST_VARIATION(1, L"GetResults from seperate threads") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // }} END_DECLARE_TEST_CASES() // {{ TCW_TESTMODULE(ThisModule) TEST_MODULE(16, ThisModule, gwszModuleDescrip) TEST_CASE(1, TCDataSource) TEST_CASE(2, TCSession) TEST_CASE(3, TCCommand) TEST_CASE(4, TCAccessor) TEST_CASE(5, TCError) TEST_CASE(6, TCTransaction) TEST_CASE(7, TCOpenRowset) TEST_CASE(8, TCRowset) TEST_CASE(9, TCRowsetChange) TEST_CASE(10, TCRowsetOther) TEST_CASE(11, TCRowsetUpdate) TEST_CASE(12, TCConnections) TEST_CASE(13, TCSequence) TEST_CASE(14, TCClassFactory) TEST_CASE(15, TCRealWorld) TEST_CASE(16, TCMultipleResult) END_TEST_MODULE() // }} TCW_TESTMODULE_END // {{ TCW_TC_PROTOTYPE(TCDataSource) //*----------------------------------------------------------------------- //| Test Case: TCDataSource - Multi-Threaded testing of the DataSourceObject //| Created: 05/21/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCDataSource::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc GetDataSource threading model CLSID // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_1() { TBEGIN ASSERT(m_pIDBInitialize); ULONG_PTR ulValue = 0; //Get ThreadingModel TESTC(VerifyThreadingModel()) //Get DataSource ThreadingModel TESTC_PROVIDER(::GetProperty(DBPROP_DSOTHREADMODEL, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulValue)); //Threading Property is one of the following, not Anded! TESTC(ulValue == DBPROPVAL_RT_FREETHREAD || ulValue == DBPROPVAL_RT_APTMTTHREAD || ulValue == DBPROPVAL_RT_SINGLETHREAD); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc GetProperties and SetProperites on the same DSO // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_2() { TBEGIN INIT_THREADS(MAX_THREADS); ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; IDBProperties* pIDBProperties = NULL; //Build our init options from string passed to us from the InitString GetInitProps(&cPropSets, &rgPropSets); //Create another instance, with properties set, (not initialized) CreateNewDSO(NULL, IID_IDBProperties,(IUnknown**)&pIDBProperties, CREATEDSO_NONE); //Setup thread arguments THREADARG T1Arg = { pIDBProperties, 0, NULL }; //All Properties THREADARG T2Arg = { pIDBProperties, (void*)cPropSets, rgPropSets }; //Half of the threads GetProperties, the other half SetProperties CREATE_FIRST_THREADS(Thread_IDBGetProperties, &T1Arg); CREATE_SECOND_THREADS(Thread_IDBSetProperties, &T2Arg); START_THREADS(); END_THREADS(); //CLEANUP: ::FreeProperties(&cPropSets,&rgPropSets); SAFE_RELEASE(pIDBProperties); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc GetProperties on the same set of properties // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_3() { TBEGIN INIT_THREADS(MAX_THREADS); ULONG cPropIDSets = 0; DBPROPIDSET* rgPropIDSets = NULL; IDBProperties* pIDBProperties = NULL; //Create another instance, with properties set, (not initialized) CreateNewDSO(NULL, IID_IDBProperties, (IUnknown**)&pIDBProperties, CREATEDSO_SETPROPERTIES); //DBPROP_INIT_PROMPT is a required level 0 property if(SupportedProperty(DBPROP_INIT_PROMPT,DBPROPSET_DBINIT)) ::SetProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT, &cPropIDSets, &rgPropIDSets); //Add DataSoruce is supported if(SupportedProperty(DBPROP_INIT_DATASOURCE,DBPROPSET_DBINIT)) ::SetProperty(DBPROP_INIT_DATASOURCE,DBPROPSET_DBINIT, &cPropIDSets, &rgPropIDSets); //Setup thread arguments THREADARG T1Arg = { pIDBProperties, (void*)cPropIDSets, rgPropIDSets }; THREADARG T2Arg = { pIDBProperties, 0, NULL }; //All Properties //Half of the threads are before Initialization, the other hald is after Initialization CREATE_FIRST_THREADS(Thread_IDBGetProperties, &T1Arg); CREATE_SECOND_THREADS(Thread_IDBGetProperties, &T2Arg); START_THREADS(); END_THREADS(); //CLEANUP: ::FreeProperties(&cPropIDSets,&rgPropIDSets); SAFE_RELEASE(pIDBProperties); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc GetPropertyInfo on all properties supported // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_4() { TBEGIN INIT_THREADS(MAX_THREADS); IDBProperties* pIDBProperties1 = NULL; IDBProperties* pIDBProperties2 = NULL; //Create another instance, with properties set, (not initialized) CreateNewDSO(NULL, IID_IDBProperties, (IUnknown**)&pIDBProperties1, CREATEDSO_SETPROPERTIES); CreateNewDSO(NULL, IID_IDBProperties, (IUnknown**)&pIDBProperties2, CREATEDSO_SETPROPERTIES | CREATEDSO_INITIALIZE); //Setup thread arguments THREADARG T1Arg = { pIDBProperties1, 0, NULL }; //Before Initialization THREADARG T2Arg = { pIDBProperties2, 0, NULL }; //After Initialization //Half of the threads are before Initialization, the other hald is after Initialization CREATE_FIRST_THREADS(Thread_IDBGetPropertyInfo, &T1Arg); CREATE_SECOND_THREADS(Thread_IDBGetPropertyInfo, &T2Arg); START_THREADS(); END_THREADS(); //CLEANUP: SAFE_RELEASE(pIDBProperties1); SAFE_RELEASE(pIDBProperties2); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc SetProperties on the same DSO // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_5() { TBEGIN INIT_THREADS(MAX_THREADS); ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; IDBProperties* pIDBProperties = NULL; //Build our init options from string passed to us from the InitString GetInitProps(&cPropSets, &rgPropSets); //Create another instance, with properties set, (not initialized) CreateNewDSO(NULL, IID_IDBProperties,(IUnknown**)&pIDBProperties, CREATEDSO_NONE); //Setup thread arguments THREADARG T1Arg = { pIDBProperties, (void*)cPropSets, rgPropSets }; CREATE_THREADS(Thread_IDBSetProperties, &T1Arg); START_THREADS(); END_THREADS(); //CLEANUP: ::FreeProperties(&cPropSets,&rgPropSets); SAFE_RELEASE(pIDBProperties); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Initialize the DSO from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_6() { TBEGIN INIT_THREADS(MAX_THREADS); //number of threads... IDBInitialize* pIDBInitialize = NULL; //Create another instance, with properties set, (not initialized) CreateNewDSO(NULL, IID_IDBInitialize,(IUnknown**)&pIDBInitialize, CREATEDSO_SETPROPERTIES); //Setup thread arguments THREADARG T1Arg = { pIDBInitialize, (void*)DB_E_ALREADYINITIALIZED }; TESTC(pIDBInitialize!=NULL); //Create Thread CREATE_THREADS(Thread_IDBInitialize, &T1Arg); START_THREADS(); END_THREADS(); CLEANUP: SAFE_RELEASE(pIDBInitialize); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Unitilize the DSO from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_7() { TBEGIN INIT_THREADS(MAX_THREADS); IDBInitialize* pIDBInitialize = NULL; //Create another instance, since our current one from the privlib has too many //references to uninitilize CreateNewDSO(NULL, IID_IDBInitialize,(IUnknown**)&pIDBInitialize, CREATEDSO_SETPROPERTIES | CREATEDSO_INITIALIZE); //Setup thread arguments THREADARG T1Arg = { pIDBInitialize, (void*)S_OK }; TESTC(pIDBInitialize!=NULL); CREATE_THREADS(Thread_IDBUninitialize, &T1Arg); START_THREADS(); END_THREADS(); CLEANUP: SAFE_RELEASE(pIDBInitialize); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Initialize / Unitialize same DSO from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_8() { TBEGIN INIT_THREADS(MAX_THREADS); //number of threads... IDBInitialize* pIDBInitialize = NULL; //Create another instance, with properties set, (not initialized) CreateNewDSO(NULL, IID_IDBInitialize,(IUnknown**)&pIDBInitialize, CREATEDSO_SETPROPERTIES); //Setup thread arguments THREADARG T1Arg = { pIDBInitialize, (void*)DB_E_ALREADYINITIALIZED }; THREADARG T2Arg = { pIDBInitialize, (void*)S_OK }; TESTC(pIDBInitialize!=NULL); //Half of the threads are before Initialization, the other hald is after Initialization CREATE_FIRST_THREADS(Thread_IDBInitialize, &T1Arg); CREATE_SECOND_THREADS(Thread_IDBUninitialize, &T2Arg); START_THREADS(); END_THREADS(); CLEANUP: SAFE_RELEASE(pIDBInitialize); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Initialize seperate DSOs in threads // // @rdesc TEST_PASS or TEST_FAIL // int TCDataSource::Variation_9() { TBEGIN INIT_THREADS(MAX_THREADS); //number of threads... ULONG cPropSets = 0; DBPROPSET* rgPropSets = NULL; //Build our init options from string passed to us from the InitString GetInitProps(&cPropSets, &rgPropSets); //Setup thread arguments //We allow E_FAIL, since this number of threads, may be over the number of connections //allowed by the DataSource and currently there is no other return code to indicate this THREADARG T1Arg = { NULL, (void*)cPropSets, rgPropSets, (void*)DB_SEC_E_AUTH_FAILED, (void*)E_FAIL }; //Create Thread CREATE_THREADS(Thread_NewDSOInitialize, &T1Arg); START_THREADS(); END_THREADS(); ::FreeProperties(&cPropSets, &rgPropSets); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCDataSource::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCSession) //*----------------------------------------------------------------------- //| Test Case: TCSession - Multi-Threaded testing of the SessionObject //| Created: 05/21/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCSession::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Get the Session Threading model CLSID // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_1() { TBEGIN //Get ThreadingModel TESTC(VerifyThreadingModel()) CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Get the Session threading model Property // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_2() { TBEGIN ASSERT(m_pIDBInitialize); ULONG_PTR ulValue = 0; //Get ThreadingModel TESTC_PROVIDER(::GetProperty(DBPROP_DSOTHREADMODEL, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulValue)); //Threading Property is one of the following, not Anded! TESTC(ulValue == DBPROPVAL_RT_FREETHREAD || ulValue == DBPROPVAL_RT_APTMTTHREAD || ulValue == DBPROPVAL_RT_SINGLETHREAD); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc CreateSession from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_3() { TBEGIN INIT_THREADS(THREE_THREADS); ULONG_PTR ulMaxSessions = 0; HRESULT hrExpected = S_OK; //Determine the Maximum Number of Actiave Sessions ::GetProperty(DBPROP_ACTIVESESSIONS, DBPROPSET_DATASOURCEINFO, g_pIDBCreateSession, &ulMaxSessions); if(ulMaxSessions!=0 && ulMaxSessions < THREE_THREADS+1) hrExpected = DB_E_OBJECTCREATIONLIMITREACHED; //Setup thread arguments THREADARG T1Arg = { this, (void*)hrExpected }; CREATE_THREADS(Thread_IDBCreateSession, &T1Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc CreateCommand from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_4() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup thread arguments THREADARG T1Arg = { this }; CREATE_THREADS(Thread_IDBCreateCommand,&T1Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_5() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Add a column / drop a column from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_6() { TBEGIN // INIT_THREADS(MAX_THREADS); //Setup thread arguments THREADARG T1Arg = { this }; //TODO V2, AddColumn/DropColumn not supported yet /* CREATE_FIRST_THREADS(Thread_AddColumn,&T1Arg); CREATE_SECOND_THREADS(Thread_DropColumn,&T1Arg); START_THREADS(); END_THREADS(); */ //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Create a table from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_7() { TBEGIN // INIT_THREADS(MAX_THREADS); //Setup thread arguments THREADARG T1Arg = { this }; //TODO V2, CreateTable not supported yet /* CREATE_THREADS(Thread_IDBCreateTable,&T1Arg); START_THREADS(); END_THREADS(); */ //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_8() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Get schema rowset from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_9() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup thread arguments THREADARG T1Arg = { this }; //IDBSchemaRowset is optional TESTC_PROVIDER(QI(pISession(),IID_IDBSchemaRowset)==S_OK); CREATE_THREADS(Thread_GetSchemaRowset,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc Get schema info from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCSession::Variation_10() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup thread arguments THREADARG T1Arg = { this }; //IDBSchemaRowset is optional TESTC_PROVIDER(QI(pISession(),IID_IDBSchemaRowset)==S_OK); CREATE_THREADS(Thread_GetSchemaInfo,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCSession::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCCommand) //*----------------------------------------------------------------------- //| Test Case: TCCommand - Multi-Threaded testing of the CommandObject //| Created: 05/21/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCCommand::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { //Skip if Commands are not uspported.. TEST_PROVIDER(GetCommandSupport()); //Create the CommandObject and Set the CommandText //For the rest of the Variations in this testcase... if(CreateCommand(SELECT_ALLFROMTBL)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Get the command threading model CLSID // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_1() { TBEGIN //Get ThreadingModel TESTC(VerifyThreadingModel()) CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Get the command threading model Property // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_2() { TBEGIN ASSERT(m_pIDBInitialize); ULONG_PTR ulValue = 0; //Get ThreadingModel TESTC_PROVIDER(::GetProperty(DBPROP_DSOTHREADMODEL, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulValue)); //Threading Property is one of the following, not Anded! TESTC(ulValue == DBPROPVAL_RT_FREETHREAD || ulValue == DBPROPVAL_RT_APTMTTHREAD || ulValue == DBPROPVAL_RT_SINGLETHREAD); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Create command objects on seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_3() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup thread arguments THREADARG T1Arg = { this }; CREATE_THREADS(Thread_IDBCreateCommand,&T1Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Call execute from sep threads, (same command object // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_4() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup thread arguments THREADARG T1Arg = { this, (void*)S_OK }; CREATE_THREADS(Thread_CommandExecute,&T1Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Call cancel while two executes are occurring // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_5() { TBEGIN INIT_THREADS(THREE_THREADS); //Setup thread arguments THREADARG T1Arg = { this, (void*)DB_E_CANCELED }; THREADARG T2Arg = { this, (void*)DB_E_CANTCANCEL }; CREATE_THREAD(THREAD_ONE, Thread_CommandExecute, &T1Arg); CREATE_THREAD(THREAD_TWO, Thread_CommandExecute, &T1Arg); CREATE_THREAD(THREAD_THREE, Thread_CommandCancel, &T2Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_6() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Set/Unset diff prop // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_7() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; //Set properties SetSettableProperty(DBPROP_CANHOLDROWS); SetSettableProperty(DBPROP_IRowsetUpdate, DBPROPSET_ROWSET,(void*)VARIANT_FALSE,DBTYPE_BOOL); RowsetA.SetSettableProperty(DBPROP_BOOKMARKS); RowsetA.SetSettableProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET,(void*)VARIANT_FALSE,DBTYPE_BOOL); //Setup thread arguments THREADARG T1Arg = { &RowsetA, (void*)m_cPropSets, m_rgPropSets }; THREADARG T2Arg = { &RowsetA, (void*)RowsetA.m_cPropSets, RowsetA.m_rgPropSets }; TESTC_(RowsetA.CreateCommand(SELECT_ALLFROMTBL),S_OK); CREATE_FIRST_THREADS(Thread_SetCommandProperties,&T1Arg); CREATE_SECOND_THREADS(Thread_SetCommandProperties,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: FreeProperties(); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Set/Unset same prop // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_8() { TBEGIN INIT_THREADS(MAX_THREADS); SetSettableProperty(DBPROP_CANHOLDROWS); SetSettableProperty(DBPROP_IRowsetUpdate, DBPROPSET_ROWSET,(void*)VARIANT_FALSE,DBTYPE_BOOL); CRowset RowsetA; RowsetA.SetSettableProperty(DBPROP_CANHOLDROWS); RowsetA.SetSettableProperty(DBPROP_IRowsetUpdate,DBPROPSET_ROWSET,(void*)VARIANT_FALSE,DBTYPE_BOOL); //Setup thread arguments THREADARG T1Arg = { &RowsetA, (void*)m_cPropSets, m_rgPropSets }; THREADARG T2Arg = { &RowsetA, (void*)RowsetA.m_cPropSets, RowsetA.m_rgPropSets }; TESTC_(RowsetA.CreateCommand(SELECT_ALLFROMTBL),S_OK); CREATE_FIRST_THREADS(Thread_SetCommandProperties,&T1Arg); CREATE_SECOND_THREADS(Thread_SetCommandProperties,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: FreeProperties(); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Get/Set prop from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_9() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; RowsetA.SetSettableProperty(DBPROP_CANHOLDROWS); RowsetA.SetSettableProperty(DBPROP_IRowsetUpdate, DBPROPSET_ROWSET, (void*)VARIANT_TRUE, DBTYPE_BOOL); ULONG cPropIDSets = 0; DBPROPIDSET* rgPropIDSets = NULL; if(SettableProperty(DBPROP_IRowsetUpdate,DBPROPSET_ROWSET)) ::SetProperty(DBPROP_IRowsetUpdate,DBPROPSET_ROWSET,&cPropIDSets,&rgPropIDSets); //Setup thread arguments THREADARG T1Arg = { &RowsetA, (void*)RowsetA.m_cPropSets, RowsetA.m_rgPropSets }; THREADARG T2Arg = { &RowsetA, (void*)cPropIDSets, rgPropIDSets }; TESTC_(RowsetA.CreateCommand(SELECT_ALLFROMTBL),S_OK); CREATE_FIRST_THREADS(Thread_SetCommandProperties,&T1Arg); CREATE_SECOND_THREADS(Thread_GetCommandProperties,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.FreeProperties(); ::FreeProperties(&cPropIDSets,&rgPropIDSets); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc Set the command text / Get text from another thread // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_10() { TBEGIN INIT_THREADS(MAX_THREADS); WCHAR* pwszCommandText = NULL; //Obtain the CommandText for "SELECT * FROM " pTable()->CreateSQLStmt(USE_SUPPORTED_SELECT_ALLFROMTBL,NULL,&pwszCommandText); //Setup thread arguments THREADARG T1Arg = { this, pwszCommandText }; THREADARG T2Arg = { this }; TESTC(pwszCommandText!=NULL) CREATE_FIRST_THREADS(Thread_SetCommandText,&T1Arg); CREATE_SECOND_THREADS(Thread_GetCommandText,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: PROVIDER_FREE(pwszCommandText); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_11() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc Uprepare / Prepare // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_12() { TBEGIN INIT_THREADS(THREE_THREADS); //Setup thread arguments THREADARG T1Arg = { this }; THREADARG T2Arg = { this, (void*)S_OK }; CREATE_THREAD(THREAD_ONE, Thread_CommandPrepare, &T1Arg); CREATE_THREAD(THREAD_TWO, Thread_CommandPrepare, &T1Arg); CREATE_THREAD(THREAD_THREE, Thread_CommandUnPrepare,&T2Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc Unprepare / Execute // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_13() { TBEGIN INIT_THREADS(THREE_THREADS); //Setup thread arguments THREADARG T1Arg = { this, (void*)S_OK }; THREADARG T2Arg = { this, (void*)DB_E_OBJECTOPEN }; //Now try and Execute the Text and Unprepare CREATE_THREAD(THREAD_ONE, Thread_CommandExecute, &T1Arg); CREATE_THREAD(THREAD_TWO, Thread_CommandUnPrepare,&T2Arg); CREATE_THREAD(THREAD_THREE, Thread_CommandUnPrepare,&T2Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_14() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc SetDefaultValues from sep threads, GetDefaultValues from a third // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_15() { TBEGIN INIT_THREADS(THREE_THREADS); //Setup thread arguments THREADARG T1Arg = { this }; CREATE_THREAD(THREAD_ONE, Thread_SetDefaultValues,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_SetDefaultValues,&T1Arg); CREATE_THREAD(THREAD_THREE, Thread_GetDefaultValues,&T1Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_16() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Execute / Release the command object // // @rdesc TEST_PASS or TEST_FAIL // int TCCommand::Variation_17() { TBEGIN INIT_THREADS(FOUR_THREADS); //Setup thread arguments THREADARG T1Arg = { this, (void*)S_OK }; THREADARG T2Arg = { pICommand() }; THREADARG T3Arg = { pICommand() }; THREADARG T4Arg = { this, (void*)DB_E_OBJECTOPEN }; //AddRef an extra time, just in case Release runs faster pICommand()->AddRef(); CREATE_THREAD(THREAD_ONE, Thread_CommandExecute,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_Release,&T2Arg); CREATE_THREAD(THREAD_THREE, Thread_AddRef,&T3Arg); CREATE_THREAD(THREAD_FOUR, Thread_CommandUnPrepare,&T4Arg); START_THREADS(); END_THREADS(); //CLEANUP: //Release the extra time pICommand()->Release(); TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCCommand::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCAccessor) //*----------------------------------------------------------------------- //| Test Case: TCAccessor - Multi-Threaded testing of the Accessor object //| Created: 05/21/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCAccessor::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Create multiple accessors from diff threads // // @rdesc TEST_PASS or TEST_FAIL // int TCAccessor::Variation_1() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup thread arguments THREADARG T1Arg = { this }; CREATE_THREADS(Thread_CreateAccessor,&T1Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Use the same accessor on diff threads // // @rdesc TEST_PASS or TEST_FAIL // int TCAccessor::Variation_2() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; HRESULT hr = S_OK; THREADARG T1Arg; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Obtain all row handles (as many row handles as possible) TEST3C_(hr = RowsetA.GetNextRows(0, 1000, &cRowsObtained, &rghRows), DB_S_ENDOFROWSET, DB_S_ROWLIMITEXCEEDED, E_OUTOFMEMORY); TESTC_PROVIDER(SUCCEEDED(hr)); //Setup Thread Arguments T1Arg = InitThreadArg(&RowsetA, (void*)cRowsObtained, rghRows, &RowsetA.m_hAccessor, (void*)S_OK); //Create Threads CREATE_THREADS(Thread_GetData, &T1Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCAccessor::Variation_3() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc GetBindiings / ReleaseAcessor // // @rdesc TEST_PASS or TEST_FAIL // int TCAccessor::Variation_4() { TBEGIN INIT_THREADS(TWO_THREADS); HACCESSOR hAccessor = NULL; CRowset RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hAccessor, (void*)DB_E_BADACCESSORHANDLE }; THREADARG T2Arg = { &RowsetA, &hAccessor }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Create another accessor TESTC_(GetAccessorAndBindings(RowsetA.pIRowset(),DBACCESSOR_ROWDATA,&hAccessor, NULL,NULL,NULL, DBPART_ALL, ALL_COLS_BOUND),S_OK); //Create Threads CREATE_FIRST_THREADS(Thread_GetBindings,&T1Arg); CREATE_SECOND_THREADS(Thread_ReleaseAccessor,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc GetColumnsInfo / IRowsetInfo // // @rdesc TEST_PASS or TEST_FAIL // int TCAccessor::Variation_5() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA, 0, NULL }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_FIRST_THREADS(Thread_GetColumnsInfo,&T1Arg); CREATE_SECOND_THREADS(Thread_GetRowsetProperties,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCAccessor::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCError) //*----------------------------------------------------------------------- //| Test Case: TCError - Multi-Threaded testing of the ErrorObject //| Created: 05/21/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCError::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Get the Error object threading model CLSID // // @rdesc TEST_PASS or TEST_FAIL // int TCError::Variation_1() { TBEGIN //Get ThreadingModel TESTC(VerifyThreadingModel()) CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Get the Error object threading model Property // // @rdesc TEST_PASS or TEST_FAIL // int TCError::Variation_2() { TBEGIN ASSERT(m_pIDBInitialize); ULONG_PTR ulValue = 0; //Get ThreadingModel TESTC_PROVIDER(::GetProperty(DBPROP_DSOTHREADMODEL, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulValue)); //Threading Property is one of the following, not Anded! TESTC(ulValue == DBPROPVAL_RT_FREETHREAD || ulValue == DBPROPVAL_RT_APTMTTHREAD || ulValue == DBPROPVAL_RT_SINGLETHREAD); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc AddErrorRecord from sep threads, GetErrorInfo from a third // // @rdesc TEST_PASS or TEST_FAIL // int TCError::Variation_3() { TBEGIN INIT_THREADS(THREE_THREADS); CRowset RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA }; THREADARG T3Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_THREAD(THREAD_ONE, Thread_AddErrorRecord,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_AddErrorRecord,&T2Arg); CREATE_THREAD(THREAD_THREE, Thread_GetErrorInfo,&T3Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Transfer error record to antoher thread. // // @rdesc TEST_PASS or TEST_FAIL // int TCError::Variation_4() { //TODO return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Apartment model - make sure apartment model error object is returned // // @rdesc TEST_PASS or TEST_FAIL // int TCError::Variation_5() { //TODO V2 return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCError::Variation_6() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Generate Errors from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCError::Variation_7() { //TODO return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Use diff threads to make IErrorInfo calls // // @rdesc TEST_PASS or TEST_FAIL // int TCError::Variation_8() { TBEGIN INIT_THREADS(THREE_THREADS); CRowset RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA }; THREADARG T3Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_THREAD(THREAD_ONE, Thread_AddErrorRecord,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_AddErrorRecord,&T2Arg); CREATE_THREAD(THREAD_THREE, Thread_GetErrorInfo,&T3Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Create Error object on 1 thread, set error info from many other threads // // @rdesc TEST_PASS or TEST_FAIL // int TCError::Variation_9() { //TODO return TEST_PASS; } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCError::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCTransaction) //*----------------------------------------------------------------------- //| Test Case: TCTransaction - Multi-Threaded testing of the TransactionObject //| Created: 05/21/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCTransaction::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Get the transaction threading model CLSID // // @rdesc TEST_PASS or TEST_FAIL // int TCTransaction::Variation_1() { TBEGIN //Get ThreadingModel TESTC(VerifyThreadingModel()) CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Get the transaction threading model Property // // @rdesc TEST_PASS or TEST_FAIL // int TCTransaction::Variation_2() { TBEGIN ASSERT(m_pIDBInitialize); ULONG_PTR ulValue = 0; //Get ThreadingModel TESTC_PROVIDER(::GetProperty(DBPROP_DSOTHREADMODEL, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulValue)); //Threading Property is one of the following, not Anded! TESTC(ulValue == DBPROPVAL_RT_FREETHREAD || ulValue == DBPROPVAL_RT_APTMTTHREAD || ulValue == DBPROPVAL_RT_SINGLETHREAD); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Two Commits, from two transactions // // @rdesc TEST_PASS or TEST_FAIL // int TCTransaction::Variation_3() { //TODO return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Multiple thread running under one transaction, commit // // @rdesc TEST_PASS or TEST_FAIL // int TCTransaction::Variation_4() { //TODO return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Multiple thread running under one transaction, abort // // @rdesc TEST_PASS or TEST_FAIL // int TCTransaction::Variation_5() { //TODO return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCTransaction::Variation_6() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc One thread aborts, while the other is doing real work // // @rdesc TEST_PASS or TEST_FAIL // int TCTransaction::Variation_7() { //TODO return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc One thread commits, while the other thread is doing real work // // @rdesc TEST_PASS or TEST_FAIL // int TCTransaction::Variation_8() { //TODO return TEST_PASS; } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCTransaction::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCOpenRowset) //*----------------------------------------------------------------------- //| Test Case: TCOpenRowset - Multi-Threaded testing of the OpenRowsetObject //| Created: 05/21/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCOpenRowset::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc QI for IID_IOpenRowset from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCOpenRowset::Variation_1() { TBEGIN INIT_THREADS(MAX_THREADS); THREADARG T1Arg; //CreateOpenRowset COpenRowset OpenRowset; TESTC_(OpenRowset.CreateOpenRowset(),S_OK); //Setup threads args T1Arg.pFunc = OpenRowset(); T1Arg.pArg1 = (void*)&IID_IOpenRowset; CREATE_THREADS(Thread_QI,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Call OpenRowset from two threads, diff prop, from the same table // // @rdesc TEST_PASS or TEST_FAIL // int TCOpenRowset::Variation_2() { TBEGIN INIT_THREADS(MAX_THREADS); COpenRowset OpenRowset; //Setup property structs ULONG cPropSets1 = 0; DBPROPSET* rgPropSets1 = NULL; ::SetSettableProperty(DBPROP_CANHOLDROWS,DBPROPSET_ROWSET,&cPropSets1,&rgPropSets1); ULONG cPropSets2 = 0; DBPROPSET* rgPropSets2 = NULL; ::SetSettableProperty(DBPROP_IRowset,DBPROPSET_ROWSET,&cPropSets2,&rgPropSets2); //Setup thread arguments THREADARG T1Arg = { &OpenRowset, (void*)cPropSets1, rgPropSets1 }; THREADARG T2Arg = { &OpenRowset, (void*)cPropSets2, rgPropSets2 }; //Create OpenRowset TESTC_(OpenRowset.CreateOpenRowset(),S_OK); CREATE_FIRST_THREADS(Thread_OpenRowset,&T1Arg); CREATE_SECOND_THREADS(Thread_OpenRowset,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: ::FreeProperties(&cPropSets1,&rgPropSets1); ::FreeProperties(&cPropSets2,&rgPropSets2); TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCOpenRowset::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCRowset) //*----------------------------------------------------------------------- //| Test Case: TCRowset - Multi-Threaded testing of the RowsetObject //| Created: 05/21/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCRowset::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_1() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Verify threading model - Free Threaded // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_2() { TBEGIN ULONG_PTR ulValue = SHRT_MAX; DBPROPFLAGS dwPropFlags; //Create a rowset CRowset RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Verify Threading model TESTC_PROVIDER(RowsetA.GetProperty(DBPROP_ROWTHREADMODEL,DBPROPSET_ROWSET,&ulValue)) //Threading Property is one of the following, not Anded! TESTC(ulValue == DBPROPVAL_RT_FREETHREAD || ulValue == DBPROPVAL_RT_APTMTTHREAD || ulValue == DBPROPVAL_RT_SINGLETHREAD); //Verify Threading Model is Read/Write dwPropFlags = GetPropInfoFlags(DBPROP_ROWTHREADMODEL, DBPROPSET_ROWSET); //If Provider supported both threading models then the property //must be Read/Write to specify how to create the objects if(ulValue == DBPROPVAL_RT_BOTH) { TESTC(BITSET(dwPropFlags, DBPROPFLAGS_READ)) TESTC(BITSET(dwPropFlags, DBPROPFLAGS_WRITE)) } //Otherwise should be Read-Only since only creates certain type of objects else { TESTC(BITSET(dwPropFlags, DBPROPFLAGS_READ)) TESTC(BITCLEAR(dwPropFlags, DBPROPFLAGS_WRITE)) } CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Verify read-only threading property // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_3() { TBEGIN DBPROP* pProp = NULL; HRESULT hr = S_OK; //Create a rowset CRowset RowsetA; TESTC_PROVIDER(RowsetA.SetSupportedProperty(DBPROP_ROWTHREADMODEL,DBPROPSET_ROWSET,(void*)ULONG_MAX,DBTYPE_I4)); //ROWTHREADMODEL is read-only, should produce an error trying to set it... TESTC_(hr = RowsetA.CreateRowset(SELECT_VALIDATIONORDER), DB_E_ERRORSOCCURRED); //Verify Property Status... TESTC(FindProperty(DBPROP_ROWTHREADMODEL,DBPROPSET_ROWSET, RowsetA.m_cPropSets, RowsetA.m_rgPropSets, &pProp)); TESTC(pProp->dwStatus == DBPROPSTATUS_NOTSETTABLE || pProp->dwStatus == DBPROPSTATUS_BADVALUE); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_4() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc QI from sep threads for diff riid's // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_5() { TBEGIN INIT_THREADS(MAX_THREADS); THREADARG T1Arg,T2Arg; CRowset RowsetA; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Setup threading args T1Arg.pFunc = RowsetA(); T1Arg.pArg1 = (void*)&IID_IRowset; T2Arg.pFunc = RowsetA(); T2Arg.pArg1 = (void*)&IID_IRowsetInfo; CREATE_FIRST_THREADS(Thread_QI,&T1Arg); CREATE_SECOND_THREADS(Thread_QI,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc AddRef / Release testing // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_6() { TBEGIN INIT_THREADS(FOUR_THREADS); THREADARG T1Arg; //CreateRowset CRowset RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Now setup the thread args T1Arg.pFunc = RowsetA(); //As a precation, so we don't acidently release the object //if the release threads get there first RowsetA()->AddRef(); RowsetA()->AddRef(); RowsetA()->AddRef(); RowsetA()->AddRef(); //T1 - AddRef, T2 - Release, T3 - AddRef, T4 - Release CREATE_THREAD(THREAD_ONE, Thread_AddRef , &T1Arg); CREATE_THREAD(THREAD_TWO, Thread_Release, &T1Arg); CREATE_THREAD(THREAD_THREE,Thread_AddRef, &T1Arg); CREATE_THREAD(THREAD_FOUR, Thread_Release, &T1Arg); START_THREADS(); END_THREADS(); //Restore original ref-count SetRefCount(RowsetA(), -4); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc AddRefRows / ReleaseRows testing // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_7() { TBEGIN INIT_THREADS(FOUR_THREADS); HROW hRow = DB_NULL_HROW; CRowset RowsetA; //We want to pass the HROW to all threads... THREADARG T1Arg = { &RowsetA, (void*)&hRow }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Obtain a row handle TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK) //AddRef the row a few times, incase of race conditions TESTC_(RowsetA()->AddRefRows(ONE_ROW,&hRow,NULL,NULL),S_OK) TESTC_(RowsetA()->AddRefRows(ONE_ROW,&hRow,NULL,NULL),S_OK) TESTC_(RowsetA()->AddRefRows(ONE_ROW,&hRow,NULL,NULL),S_OK) TESTC_(RowsetA()->AddRefRows(ONE_ROW,&hRow,NULL,NULL),S_OK) TESTC_(RowsetA()->AddRefRows(ONE_ROW,&hRow,NULL,NULL),S_OK) //T1 - AddRef, T2 - Release, T3 - AddRef, T4 - Release CREATE_THREAD(THREAD_ONE, Thread_AddRefRows, &T1Arg); CREATE_THREAD(THREAD_TWO, Thread_ReleaseRows,&T1Arg); CREATE_THREAD(THREAD_THREE,Thread_AddRefRows, &T1Arg); CREATE_THREAD(THREAD_FOUR, Thread_ReleaseRows,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: //Restore original row ref-count RowsetA.ReleaseRows(hRow); RowsetA.ReleaseRows(hRow); RowsetA.ReleaseRows(hRow); RowsetA.ReleaseRows(hRow); RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_8() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc GetNextRows from multiple threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_9() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; //Setup threading args THREADARG T1Arg = { &RowsetA, (void*)0, (void*)ONE_ROW, (void*)DB_S_ENDOFROWSET }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_THREADS(Thread_GetNextRows, &T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc GetNextRows from multiple threads, with overlapping set of rows // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_10() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; //We want to pass the HROW to all threads... THREADARG T1Arg = { &RowsetA, (void*)0, (void*)FOUR_ROWS, (void*)DB_S_ENDOFROWSET }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_THREADS(Thread_GetNextRows,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc GetNextRows and GetData from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_11() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)0, (void*)FOUR_ROWS, (void*)DB_S_ENDOFROWSET }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetData,&T1Arg); CREATE_SECOND_THREADS(Thread_GetNextRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_12() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc RestartPosition with GetNextRows // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_13() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)0, (void*)FOUR_ROWS, (void*)DB_S_ENDOFROWSET }; THREADARG T2Arg = { &RowsetA, (void*)FALSE }; //FALSE - rows not released //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_FIRST_THREADS(Thread_GetNextRows,&T1Arg); CREATE_SECOND_THREADS(Thread_RestartPosition,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc RestartPosition with GetData // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_14() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)FALSE };//FALSE - rows not released //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_SECOND_THREADS(Thread_GetData,&T1Arg); CREATE_FIRST_THREADS(Thread_RestartPosition,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_15() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Release a row being accessed by GetNextRows // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_16() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; HROW hRow = NULL; //We want to pass the HROW to all threads... THREADARG T1Arg = { &RowsetA, (void*)0, (void*)FOUR_ROWS, (void*)DB_S_ENDOFROWSET }; THREADARG T2Arg = { &RowsetA, &hRow, (void*)DB_E_ERRORSOCCURRED }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Grab the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetNextRows,&T1Arg); CREATE_SECOND_THREADS(Thread_ReleaseRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Delete a row, being accessed by GetData // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_17() { TBEGIN INIT_THREADS(TWO_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)DB_E_DELETEDROW }; THREADARG T2Arg = { &RowsetA, (void*)ONE_ROW, &hRow, (void*)DB_E_ERRORSOCCURRED }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetData, &T1Arg); CREATE_SECOND_THREADS(Thread_DeleteRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc Release the rowset while being used by another // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_18() { TBEGIN INIT_THREADS(THREE_THREADS); CRowset RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg, T3Arg; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Finsih setting up thread args T2Arg.pFunc = RowsetA(); T3Arg.pFunc = RowsetA(); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_THREAD(THREAD_ONE, Thread_GetData,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_Release,&T2Arg); CREATE_THREAD(THREAD_THREE, Thread_AddRef,&T3Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_19() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc GetData, same row, same accessor, diff threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_20() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG TArg1 = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_THREADS(Thread_GetData,&TArg1); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc GetData, same row, diff accessor, diff threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowset::Variation_21() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; HROW hRow = NULL; HACCESSOR hAccessor2 = NULL; //Setup Thread Arguments THREADARG TArg1 = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG TArg2 = { &RowsetA, (void*)ONE_ROW, &hRow, &hAccessor2, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Create another accessor TESTC_(GetAccessorAndBindings(RowsetA(),DBACCESSOR_ROWDATA,&hAccessor2, NULL,NULL,NULL, DBPART_ALL, ALL_COLS_BOUND),S_OK) //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetData,&TArg1); CREATE_SECOND_THREADS(Thread_GetData,&TArg2); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor2); TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCRowset::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCRowsetChange) //*----------------------------------------------------------------------- //| Test Case: TCRowsetChange - Multi-Threaded testing of the RowsetChange Object //| Created: 05/28/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCRowsetChange::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { TEST_PROVIDER(CreateRowset(DBPROP_IRowsetChange)==S_OK); return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc SetData, diff columns, from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetChange::Variation_1() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG TArg1 = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG TArg2 = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&TArg1); CREATE_SECOND_THREADS(Thread_SetData,&TArg2); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc SetData, same columns, from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetChange::Variation_2() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG TArg1 = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG TArg2 = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData, &TArg1); CREATE_SECOND_THREADS(Thread_SetData, &TArg2); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetChange::Variation_3() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc DeleteRows from seperate threads, with overlapping set of rows // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetChange::Variation_4() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; ULONG cRows = FOUR_ROWS; HROW rghRow[FOUR_ROWS] = { NULL,NULL,NULL,NULL }; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)cRows, rghRow, (void*)DB_E_ERRORSOCCURRED, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,FOUR_ROWS,rghRow),S_OK) //Create Threads CREATE_THREADS(Thread_DeleteRows,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TableInsert(TWO_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetChange::Variation_5() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Insert a row from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetChange::Variation_6() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData, &T1Arg); CREATE_SECOND_THREADS(Thread_SetData, &T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetChange::Variation_7() { return TEST_PASS; } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCRowsetChange::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCRowsetOther) //*----------------------------------------------------------------------- //| Test Case: TCRowsetOther - Multi-Threaded testing of the other Rowset variants //| Created: 05/28/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCRowsetOther::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, USE_OPENROWSET)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc GetProperties from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_1() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup Thread Arguments ULONG cPropIDSets1 = 0; DBPROPIDSET* rgPropIDSets1 = NULL; if(SettableProperty(DBPROP_CANHOLDROWS,DBPROPSET_ROWSET)) ::SetProperty(DBPROP_CANHOLDROWS,DBPROPSET_ROWSET,&cPropIDSets1,&rgPropIDSets1); ULONG cPropIDSets2 = 0; DBPROPIDSET* rgPropIDSets2 = NULL; if(SettableProperty(DBPROP_CANSCROLLBACKWARDS,DBPROPSET_ROWSET)) ::SetProperty(DBPROP_CANSCROLLBACKWARDS,DBPROPSET_ROWSET,&cPropIDSets2,&rgPropIDSets2); THREADARG GetPropArg1 = { this, (void*)cPropIDSets1, rgPropIDSets1 }; THREADARG GetPropArg2 = { this, (void*)cPropIDSets2, rgPropIDSets2 }; //Create Threads CREATE_FIRST_THREADS(Thread_GetRowsetProperties,&GetPropArg1); CREATE_SECOND_THREADS(Thread_GetRowsetProperties,&GetPropArg2); START_THREADS(); END_THREADS(); //CLEANUP: ::FreeProperties(&cPropIDSets1,&rgPropIDSets1); ::FreeProperties(&cPropIDSets2,&rgPropIDSets2); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc GetProperties while Releasing the Rowset // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_2() { TBEGIN INIT_THREADS(THREE_THREADS); ULONG cPropIDSets = 0; DBPROPIDSET* rgPropIDSets = NULL; if(SettableProperty(DBPROP_CANHOLDROWS,DBPROPSET_ROWSET)) ::SetProperty(DBPROP_CANHOLDROWS,DBPROPSET_ROWSET,&cPropIDSets,&rgPropIDSets); //Setup Thread Arguments THREADARG T1Arg = { this, (void*)cPropIDSets, rgPropIDSets }; THREADARG T2Arg = { pIRowset() }; THREADARG T3Arg = { pIRowset() }; //Create Threads CREATE_THREAD(THREAD_ONE, Thread_GetRowsetProperties,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_Release,&T2Arg); CREATE_THREAD(THREAD_THREE, Thread_AddRef,&T3Arg); START_THREADS(); END_THREADS(); //CLEANUP: ::FreeProperties(&cPropIDSets,&rgPropIDSets); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc GetSpecification from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_3() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup Thread Arguments THREADARG GetSpecArg = { this, (void*)&IID_IGetDataSource }; //Create Threads CREATE_THREADS(Thread_GetSpecification,&GetSpecArg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_4() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Requery from seperate threads, V2 // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_5() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup Thread Arguments THREADARG T1Arg = { this }; //Create Threads CREATE_THREADS(Thread_Requery,&T1Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_6() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc GetRowsAt with a set of overlapping rows from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_7() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; //CreateRowset RowsetA.SetSettableProperty(DBPROP_CANHOLDROWS); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IRowsetLocate, SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_THREADS(Thread_GetRowsAt,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc GetRowsByBookmark with a set of overlapping rows from different threads // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_8() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; DBBKMARK cbBookmark = 0; BYTE* pBookmark = NULL; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &cbBookmark, &pBookmark }; //CreateRowset RowsetA.SetProperty(DBPROP_CANHOLDROWS); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IRowsetLocate, SELECT_VALIDATIONORDER)==S_OK); //Get the first row RowsetA.GetRow(FIRST_ROW, &hRow); //Get the Bookmark info, this alloc the space for the bookmark RowsetA.GetBookmark(hRow, &cbBookmark, &pBookmark); //Create Threads CREATE_THREADS(Thread_GetRowsByBookmark,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pBookmark); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_9() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc GetVisibleData while resyncing the rows // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetOther::Variation_10() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &RowsetA.m_hAccessor }; THREADARG T2Arg = { &RowsetA }; //CreateRowset RowsetA.SetProperty(DBPROP_IRowsetResynch); RowsetA.SetProperty(DBPROP_IRowsetLocate); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetVisibleData,&T1Arg); CREATE_SECOND_THREADS(Thread_ResynchRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCRowsetOther::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCRowsetUpdate) //*----------------------------------------------------------------------- //| Test Case: TCRowsetUpdate - Multi-Threaded testing of the RowsetUpdate Object //| Created: 05/28/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCRowsetUpdate::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { TEST_PROVIDER(CreateRowset(DBPROP_IRowsetUpdate)==S_OK); return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_1() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_2() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_3() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc GetPendingRows while GetRowStatus // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_4() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; ULONG cRows = FOUR_ROWS; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA, &cRows, rghRow, (void*)DB_S_ERRORSOCCURRED, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_THREE]),S_OK) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetPendingRows,&T1Arg); CREATE_SECOND_THREADS(Thread_GetRowStatus,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc GetPendingrows while Update // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_5() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; const int cRows = FOUR_ROWS; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_THREE]),S_OK) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetPendingRows,&T1Arg); CREATE_SECOND_THREADS(Thread_Update,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc GetPendingRows while Undo // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_6() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; const int cRows = FOUR_ROWS; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetPendingRows,&T1Arg); CREATE_SECOND_THREADS(Thread_Undo,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_7() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc GetOriginalData while Update // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_8() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &rghRow[ROW_ONE], &RowsetA.m_hAccessor }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetOriginalData,&T1Arg); CREATE_SECOND_THREADS(Thread_Update,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc GetOriginalData while GetVisibleData // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_9() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &rghRow[ROW_ONE], &RowsetA.m_hAccessor }; THREADARG T2Arg = { &RowsetA, &rghRow[ROW_ONE], &RowsetA.m_hAccessor }; //CreateRowset RowsetA.SetProperty(DBPROP_IRowsetResynch); RowsetA.SetProperty(DBPROP_IRowsetLocate); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetOriginalData,&T1Arg); CREATE_SECOND_THREADS(Thread_GetVisibleData,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_10() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc Undo while Update // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_11() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; const int cRows = FOUR_ROWS; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_Update,&T1Arg); CREATE_SECOND_THREADS(Thread_Undo,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_12() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc Insert while Update // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_13() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &RowsetA.m_hAccessor, (void*)DB_E_MAXPENDCHANGESEXCEEDED }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_InsertRow,&T1Arg); CREATE_SECOND_THREADS(Thread_Update,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc Modify while Update // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_14() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; HROW rghRow[FIVE_ROWS] = {NULL,NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &rghRow[ROW_ONE], &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_ORDERBYNUMERIC, IID_IRowset, NULL, DBACCESSOR_ROWDATA, DBPART_ALL, UPDATEABLE_COLS_BOUND | NONINDEX_COLS_BOUND)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,FOUR_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]) ,S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_Update,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc Delete while Update // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_15() { TBEGIN INIT_THREADS(TWO_THREADS); CRowsetUpdate RowsetA; ULONG cRows = 0; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)FOUR_ROWS, rghRow, (void*)DB_S_ERRORSOCCURRED, (void*)DB_E_ERRORSOCCURRED }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) cRows++; //Make some change(s) if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK) cRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_THREE]),S_OK) cRows++; } if(RowsetA.AllowPendingRows(4)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) cRows++; } //Create Threads CREATE_FIRST_THREADS(Thread_DeleteRows,&T1Arg); CREATE_SECOND_THREADS(Thread_Update,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TableInsert(FIVE_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_16() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Insert while Undo // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_17() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &RowsetA.m_hAccessor, (void*)DB_E_MAXPENDCHANGESEXCEEDED }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_InsertRow,&T1Arg); CREATE_SECOND_THREADS(Thread_Undo,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc Modify while Undo // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_18() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &rghRow[ROW_ONE], &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_THREE]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_Undo,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc Delete while Undo // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_19() { TBEGIN INIT_THREADS(TWO_THREADS); CRowsetUpdate RowsetA; ULONG cRows = 0; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)cRows, rghRow, (void*)DB_E_ERRORSOCCURRED, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) cRows++; //Make some change(s) if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK) cRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) cRows++; } //Create Threads T1Arg.pArg1 = (void*)cRows; CREATE_FIRST_THREADS(Thread_DeleteRows,&T1Arg); CREATE_SECOND_THREADS(Thread_Update,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TableInsert(FOUR_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_20() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc Update while Resynch // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_21() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; const int cRows = FOUR_ROWS; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA }; //CreateRowset RowsetA.SetProperty(DBPROP_IRowsetResynch); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_THREE]),S_OK) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_Update,&T1Arg); CREATE_SECOND_THREADS(Thread_ResynchRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(22) //*----------------------------------------------------------------------- // @mfunc Undo while Resynch // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_22() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; const int cRows = FOUR_ROWS; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA }; //CreateRowset RowsetA.SetProperty(DBPROP_IRowsetResynch); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_ResynchRows,&T1Arg); CREATE_SECOND_THREADS(Thread_Undo,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(23) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_23() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(24) //*----------------------------------------------------------------------- // @mfunc Requery while Updating // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_24() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; const int cRows = FOUR_ROWS; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_Update,&T1Arg); CREATE_SECOND_THREADS(Thread_Requery,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(25) //*----------------------------------------------------------------------- // @mfunc Requerying while Undo // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_25() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; const int cRows = FOUR_ROWS; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_THREE]),S_OK) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_Requery,&T1Arg); CREATE_SECOND_THREADS(Thread_Undo,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(26) //*----------------------------------------------------------------------- // @mfunc Requery while GetOriginalData // // @rdesc TEST_PASS or TEST_FAIL // int TCRowsetUpdate::Variation_26() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetUpdate RowsetA; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &rghRow[ROW_ONE], &RowsetA.m_hAccessor }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK) //Make some change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetOriginalData,&T1Arg); CREATE_SECOND_THREADS(Thread_Requery,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCRowsetUpdate::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCConnections) //*----------------------------------------------------------------------- //| Test Case: TCConnections - Multi-Threaded testing of the RowsetNotify and related Objects //| Created: 05/28/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCConnections::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { TEST_PROVIDER(SupportedInterface(IID_IRowsetNotify, ROWSET_INTERFACE)); return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Multiple Listeners on sep threads, ROW_ACTIVE sent to all threads on their own thread // // @rdesc TEST_PASS or TEST_FAIL // int TCConnections::Variation_1() { TBEGIN INIT_THREADS(THREE_THREADS); CRowset RowsetA; DBCOUNTITEM cRowsObtained = 0; HROW* rghRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IConnectionPointContainer)==S_OK); //Create Threads CREATE_THREAD(THREAD_ONE, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_THREE, Thread_CreateListener,&T1Arg); START_THREADS(); SleepEx(3000, FALSE); //Let the other threads actually get hookup and Listening //Now cause the ROW_ACTIVE notifciation to occur //Our methods might not be thread-safe, so make a direct call to GetNextRows QTESTC_(RowsetA()->GetNextRows(NULL,0,ONE_ROW,&cRowsObtained,&rghRow),S_OK) END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(ONE_ROW,rghRow); PROVIDER_FREE(rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Multiple Listeners on sep threads, GetNextRows / Modify - all notifcations go to all threads on their own thread // // @rdesc TEST_PASS or TEST_FAIL // int TCConnections::Variation_2() { TBEGIN INIT_THREADS(THREE_THREADS); CRowset RowsetA; DBCOUNTITEM cRowsObtained = 0; HROW* rghRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IConnectionPointContainer)==S_OK); //Create Threads CREATE_THREAD(THREAD_ONE, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_THREE, Thread_CreateListener,&T1Arg); START_THREADS(); SleepEx(3000, FALSE); //Let the other threads actually get hookup and Listening //Now cause the ROW_ACTIVE notifciation to occur //Our methods might not be thread-safe, so make a direct call to GetNextRows QTESTC_(RowsetA()->GetNextRows(NULL,0,ONE_ROW,&cRowsObtained,&rghRow),S_OK) END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(ONE_ROW,rghRow); PROVIDER_FREE(rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCConnections::Variation_3() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Multiple Listeners on sep threads, as well as the main thread being a listener // // @rdesc TEST_PASS or TEST_FAIL // int TCConnections::Variation_4() { TBEGIN INIT_THREADS(THREE_THREADS); CRowset RowsetA; DBCOUNTITEM cRowsObtained = 0; HROW* rghRow = NULL; DWORD dwCookie = 0; CListener* pCListener = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IConnectionPointContainer)==S_OK); //Main thread Listener, off the Rowset pCListener = new CListener(IID_IRowsetNotify, RowsetA()); TESTC(pCListener!=NULL); pCListener->AddRef(); pCListener->Advise(&dwCookie); //Create Threads CREATE_THREAD(THREAD_ONE, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_THREE, Thread_CreateListener,&T1Arg); START_THREADS(); SleepEx(3000, FALSE); //Let the other threads actually get hookup and Listening //Now cause the ROW_ACTIVE notifciation to occur //Our methods might not be thread-safe, so make a direct call to GetNextRows QTESTC_(RowsetA()->GetNextRows(NULL,0,ONE_ROW,&cRowsObtained,&rghRow),S_OK) END_THREADS(); //Verify the main thread was also notified TESTC(pCListener->GetTimesNotified() > 0) CLEANUP: //Release handle(s) if(pCListener) pCListener->Unadvise(dwCookie); SAFE_RELEASE(pCListener); RowsetA.ReleaseRows(ONE_ROW,rghRow); PROVIDER_FREE(rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCConnections::Variation_5() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Two listeners on the same thread, as well as other single threaded listeners // // @rdesc TEST_PASS or TEST_FAIL // int TCConnections::Variation_6() { TBEGIN INIT_THREADS(THREE_THREADS); CRowset RowsetA; DBCOUNTITEM cRowsObtained = 0; HROW* rghRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IConnectionPointContainer)==S_OK); //Create Threads CREATE_THREAD(THREAD_ONE, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_THREE, Thread_CreateListener,&T1Arg); START_THREADS(); SleepEx(3000, FALSE); //Let the other threads actually get hookup and Listening //Now cause the ROW_ACTIVE notifciation to occur //Our methods might not be thread-safe, so make a direct call to GetNextRows QTESTC_(RowsetA()->GetNextRows(NULL,0,ONE_ROW,&cRowsObtained,&rghRow),S_OK) END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(ONE_ROW,rghRow); PROVIDER_FREE(rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCConnections::Variation_7() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc All apartment model listeners // // @rdesc TEST_PASS or TEST_FAIL // int TCConnections::Variation_8() { //TODO V2 return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Some Apartment, Some Free-Threaded lsiteners // // @rdesc TEST_PASS or TEST_FAIL // int TCConnections::Variation_9() { TBEGIN INIT_THREADS(THREE_THREADS); CRowset RowsetA; DBCOUNTITEM cRowsObtained = 0; HROW* rghRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IConnectionPointContainer)==S_OK); //Create Threads CREATE_THREAD(THREAD_ONE, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_CreateListener,&T1Arg); CREATE_THREAD(THREAD_THREE, Thread_CreateListener,&T1Arg); //TODO V2 ApartmentModel Listeners START_THREADS(); SleepEx(3000, FALSE); //Let the other threads actually get hookup and Listening //Now cause the ROW_ACTIVE notifciation to occur //Our methods might not be thread-safe, so make a direct call to GetNextRows QTESTC_(RowsetA()->GetNextRows(NULL,0,ONE_ROW,&cRowsObtained,&rghRow),S_OK) END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(ONE_ROW,rghRow); PROVIDER_FREE(rghRow); TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCConnections::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCSequence) //*----------------------------------------------------------------------- //| Test Case: TCSequence - Multi-Threaded testing of the various Rowset Objects together //| Created: 05/28/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCSequence::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc SetData multiple times // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_1() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_SetData,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc SetData for different columns within the same row // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_2() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_SetData,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc SetData and GetData for the same column/row // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_3() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_GetData,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_4() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc SetData and Resynch // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_5() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IRowsetResynch, SELECT_VALIDATIONORDER)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_ResynchRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc GetData and Resynch // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_6() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IRowsetResynch, SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetData,&T1Arg); CREATE_SECOND_THREADS(Thread_ResynchRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_7() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Insert a row while GetNextRows // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_8() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)0, (void*)ONE_ROW, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_FIRST_THREADS(Thread_InsertRow,&T1Arg); CREATE_SECOND_THREADS(Thread_GetNextRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Insert a row while GetData // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_9() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_InsertRow,&T1Arg); CREATE_SECOND_THREADS(Thread_GetData,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc Insert a row while DeleteRows // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_10() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)FOUR_ROWS, rghRow, (void*)DB_E_ERRORSOCCURRED, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_InsertRow,&T1Arg); CREATE_SECOND_THREADS(Thread_DeleteRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_11() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc Modify a row while GetNextRows // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_12() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)0, (void*)ONE_ROW, (void*)DB_S_ENDOFROWSET }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_GetNextRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc Modify a row while GetData // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_13() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_GetData,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc Modify a row while ReleaseRows // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_14() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)DB_E_BADROWHANDLE }; THREADARG T2Arg = { &RowsetA, &hRow, (void*)DB_E_ERRORSOCCURRED }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_ReleaseRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_15() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Delete a row, while GetNextRows // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_16() { TBEGIN INIT_THREADS(TWO_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, (void*)DB_E_ERRORSOCCURRED, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)0, (void*)ONE_ROW, (void*)DB_E_BADSTARTPOSITION }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_DeleteRows,&T1Arg); CREATE_SECOND_THREADS(Thread_GetNextRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Delete a row, while GetData // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_17() { TBEGIN INIT_THREADS(TWO_THREADS); CRowsetChange RowsetA; HROW rghRows[TWO_ROWS] = {NULL,NULL}; //NOTE: Its invalid to call GetData with a deleterow handle. Its totally //provider specific. So the best we can do is to call GetData and DeleteRows //from seperate threads on different row handles, becuase the DeleteRows might //get the before the GetData, possibly causing it to crash... //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &rghRows[ROW_ONE], &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)ONE_ROW, &rghRows[ROW_TWO], (void*)DB_E_ERRORSOCCURRED, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, TWO_ROWS, rghRows),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetData,&T1Arg); CREATE_SECOND_THREADS(Thread_DeleteRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(TWO_ROWS,rghRows); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc Delete a row, while SetData // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_18() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)DB_E_DELETEDROW }; THREADARG T2Arg = { &RowsetA, (void*)ONE_ROW, &hRow, (void*)DB_E_ERRORSOCCURRED, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_DeleteRows,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc Delete a row, while ReleaseRows // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_19() { TBEGIN INIT_THREADS(TWO_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, (void*)DB_E_ERRORSOCCURRED, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, &hRow, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_DeleteRows,&T1Arg); CREATE_SECOND_THREADS(Thread_ReleaseRows,&T2Arg); START_THREADS(); WAITFOR_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_20() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc Requery while DeleteRows // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_21() { TBEGIN INIT_THREADS(TWO_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, (void*)DB_E_ERRORSOCCURRED, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_DeleteRows,&T1Arg); CREATE_SECOND_THREADS(Thread_Requery,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: //Release handle(s) RowsetA.ReleaseRows(hRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(22) //*----------------------------------------------------------------------- // @mfunc Requery while Modifying and row // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_22() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_Requery,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hAccessor); RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(23) //*----------------------------------------------------------------------- // @mfunc Requery while Inserting a row // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_23() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_FIRST_THREADS(Thread_InsertRow,&T1Arg); CREATE_SECOND_THREADS(Thread_Requery,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(24) //*----------------------------------------------------------------------- // @mfunc Requery while GetNextRows // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_24() { TBEGIN INIT_THREADS(TWO_THREADS); //CRowsetChange RowsetA; CRowset RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)0, (void*)ONE_ROW, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_FIRST_THREADS(Thread_Requery,&T1Arg); CREATE_SECOND_THREADS(Thread_GetNextRows,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(25) //*----------------------------------------------------------------------- // @mfunc Requery while GetData // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_25() { TBEGIN INIT_THREADS(TWO_THREADS); CRowset RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetData,&T1Arg); CREATE_SECOND_THREADS(Thread_Requery,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(26) //*----------------------------------------------------------------------- // @mfunc Requery while RestartPosition (causing a requery // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_26() { TBEGIN INIT_THREADS(MAX_THREADS); //CRowsetChange RowsetA; CRowset RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)TRUE }; THREADARG T2Arg = { &RowsetA }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_FIRST_THREADS(Thread_RestartPosition,&T1Arg); CREATE_SECOND_THREADS(Thread_Requery,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(27) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_27() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(28) //*----------------------------------------------------------------------- // @mfunc GetNextRows while Locate // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_28() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)0, (void*)ONE_ROW, (void*)DB_S_ENDOFROWSET }; //CreateRowset RowsetA.SetProperty(DBPROP_IRowsetLocate); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Create Threads CREATE_FIRST_THREADS(Thread_GetNextRows,&T1Arg); CREATE_SECOND_THREADS(Thread_GetRowsAt,&T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(29) //*----------------------------------------------------------------------- // @mfunc GetData while Locate // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_29() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA }; //CreateRowset RowsetA.SetProperty(DBPROP_IRowsetLocate); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_GetData, &T1Arg); CREATE_SECOND_THREADS(Thread_GetRowsAt,&T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(30) //*----------------------------------------------------------------------- // @mfunc RestartPosition while Locate // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_30() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)FALSE };//FALSE - rows not released THREADARG T2Arg = { &RowsetA }; //CreateRowset RowsetA.SetProperty(DBPROP_IRowsetLocate); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK); //Actually fetch a row to force requery TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_RestartPosition, &T1Arg); CREATE_SECOND_THREADS(Thread_GetRowsAt, &T2Arg); START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(31) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCSequence::Variation_31() { return TEST_PASS; } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCSequence::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCClassFactory) //*----------------------------------------------------------------------- //| Test Case: TCClassFactory - Multi-Threaded testing of the ClassFactory object //| Created: 05/30/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCClassFactory::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Call CoCreateobject instead of CoCreateInstance // // @rdesc TEST_PASS or TEST_FAIL // int TCClassFactory::Variation_1() { TBEGIN INIT_THREADS(FOUR_THREADS); IClassFactory* pIClassFactory = NULL; //Get the ClassFactory CoGetClassObject(PROVIDER_CLSID,CLSCTX_INPROC_SERVER,NULL,IID_IClassFactory,(void**)&pIClassFactory); ASSERT(pIClassFactory); //Setup Thread Arguments THREADARG T1Arg = { this }; THREADARG T2Arg = { pIClassFactory }; //Create Threads CREATE_THREAD(THREAD_ONE, Thread_GetClassFactory,&T1Arg); CREATE_THREAD(THREAD_TWO, Thread_GetClassFactory,&T1Arg); CREATE_THREAD(THREAD_THREE, Thread_CreateInstance,&T2Arg); CREATE_THREAD(THREAD_FOUR, Thread_CreateInstance,&T2Arg); START_THREADS(); END_THREADS(); //CLEANUP: SAFE_RELEASE(pIClassFactory); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCClassFactory::Variation_2() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc PersistFile save, load from sep threads // // @rdesc TEST_PASS or TEST_FAIL // int TCClassFactory::Variation_3() { TBEGIN INIT_THREADS(MAX_THREADS); IDBInitialize* pIDBInitialize = NULL; //Create another instance, since our current one from the privlib has too many //references to uninitilize GetModInfo()->CreateProvider(NULL, IID_IDBInitialize, (IUnknown**)&pIDBInitialize); //Setup thread arguments THREADARG T1Arg = { pIDBInitialize }; TESTC(pIDBInitialize!=NULL); //Main Thread Saves TESTC_PROVIDER(SaveDSO(PERSIST_FILE)==S_OK); //Create Threads //Load from seperate threads CREATE_THREADS(Thread_PersistFileLoad, &T1Arg); START_THREADS(); END_THREADS(); CLEANUP: SAFE_RELEASE(pIDBInitialize); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Extended Error object // // @rdesc TEST_PASS or TEST_FAIL // int TCClassFactory::Variation_4() { //TODO return TEST_PASS; } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCClassFactory::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCRealWorld) //*----------------------------------------------------------------------- //| Test Case: TCRealWorld - Real-World MultiThreaded senarios for OLEDB //| Created: 05/30/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCRealWorld::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { TEST_PROVIDER(CreateRowset(DBPROP_CANHOLDROWS, SELECT_ALLFROMTBL)==S_OK); return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Browser app, reading multiple columns concurrently // // @rdesc TEST_PASS or TEST_FAIL // int TCRealWorld::Variation_1() { TBEGIN INIT_THREADS(MAX_THREADS); CRowset RowsetA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &RowsetA.m_hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_ALLFROMTBL)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_THREADS(Thread_GetData, &T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc On-Line database // // @rdesc TEST_PASS or TEST_FAIL // int TCRealWorld::Variation_2() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; HROW hRow = NULL; HACCESSOR hAccessor = NULL; //Setup Thread Arguments THREADARG T1Arg = { &RowsetA, &hRow, &hAccessor, (void*)S_OK }; THREADARG T2Arg = { &RowsetA, (void*)ONE_ROW, &hRow, &hAccessor, (void*)S_OK }; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_ALLFROMTBL)==S_OK); //Since SQLServer has a problem trying to reposition on a row if the index //column has changed, don't change the index column, bind all columns except that one TESTC_(GetAccessorAndBindings(RowsetA.pIAccessor(), DBACCESSOR_ROWDATA, &hAccessor, NULL, NULL, NULL, DBPART_ALL, UPDATEABLE_NONINDEX_COLS_BOUND),S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK) //Create Threads CREATE_FIRST_THREADS(Thread_SetData,&T1Arg); CREATE_SECOND_THREADS(Thread_GetData,&T2Arg); //TODO These threads really should be long senarios... START_THREADS(); END_THREADS(); CLEANUP: RowsetA.ReleaseRows(hRow); RowsetA.ReleaseAccessor(hAccessor); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Multiple Querys on the same Connection Object // // @rdesc TEST_PASS or TEST_FAIL // int TCRealWorld::Variation_3() { TBEGIN INIT_THREADS(MAX_THREADS); //Setup thread arguments THREADARG T1Arg = { this, (void*)S_OK }; //CreateCommandObject before entering threads CreateCommandObject(); CREATE_THREADS(Thread_CommandExecute,&T1Arg); START_THREADS(); END_THREADS(); //CLEANUP: TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCRealWorld::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCMultipleResult) //*----------------------------------------------------------------------- //| Test Case: TCMultipleResult - Multi-Threaded testing for IMultipleResults //| Created: 11/21/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCMultipleResult::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CThreads::Init()) // }} { if(CreateRowset(DBPROP_CANHOLDROWS, SELECT_VALIDATIONORDER)==S_OK) return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //-------------------------------------------------------------------- // @mfunc GetResults from seperate threads // // @rdesc TEST_PASS or TEST_FAIL // int TCMultipleResult::Variation_1() { TBEGIN INIT_THREADS(THREE_THREADS); THREADARG T1Arg, T2Arg, T3Arg; IMultipleResults* pIMultipleResults = NULL; IRowset* rgpIRowset[THREE_THREADS] = { NULL, NULL, NULL }; CRowset RowsetA; //CreateRowset TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_VALIDATIONORDER)==S_OK); //Obtain the MultipleResults interface //This is an optional interface. TESTC_PROVIDER(pTable()->ExecuteCommand(SELECT_ALLFROMTBL, IID_IMultipleResults, NULL, NULL, NULL, NULL, EXECUTE_IFNOERROR, 0, NULL, NULL, (IUnknown**)&pIMultipleResults, NULL)==S_OK); //Setup thread arguments T1Arg.pFunc = this; T1Arg.pArg1 = pIMultipleResults; T1Arg.pArg2 = &rgpIRowset[THREAD_ONE]; T2Arg.pFunc = this; T2Arg.pArg1 = pIMultipleResults; T2Arg.pArg2 = &rgpIRowset[THREAD_TWO]; T3Arg.pFunc = this; T3Arg.pArg1 = pIMultipleResults; T3Arg.pArg2 = &rgpIRowset[THREAD_THREE]; CREATE_THREAD(THREAD_ONE, Thread_GetResult, &T1Arg); CREATE_THREAD(THREAD_TWO, Thread_GetResult, &T2Arg); CREATE_THREAD(THREAD_THREE, Thread_GetResult, &T3Arg); //Execute threads START_THREADS(); END_THREADS(); //Verify results //1 thread should have executed the statment, the other 2 should have no results if(rgpIRowset[THREAD_ONE]) { TESTC(rgpIRowset[THREAD_TWO]==NULL && rgpIRowset[THREAD_THREE]==NULL); } else if(rgpIRowset[THREAD_TWO]) { TESTC(rgpIRowset[THREAD_ONE]==NULL && rgpIRowset[THREAD_THREE]==NULL); } else if(rgpIRowset[THREAD_THREE]) { TESTC(rgpIRowset[THREAD_ONE]==NULL && rgpIRowset[THREAD_TWO]==NULL); } else { TESTC(0); //Error, there was no rowset } CLEANUP: SAFE_RELEASE(pIMultipleResults); SAFE_RELEASE(rgpIRowset[THREAD_ONE]); SAFE_RELEASE(rgpIRowset[THREAD_TWO]); SAFE_RELEASE(rgpIRowset[THREAD_THREE]); TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCMultipleResult::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CThreads::Terminate()); } // }} // }} // }}