//-------------------------------------------------------------------- // Microsoft OLE DB Test // // Copyright (C) 1995-2000 Microsoft Corporation // // @doc // // @module IRowChange.cpp | This module tests the OLEDB IRowChange interface // #include "MODStandard.hpp" // Standard headers #include "IRowChange.h" // IRowChange header #include "ExtraLib.h" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Module Values // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // {{ TCW_MODULE_GLOBALS DECLARE_MODULE_CLSID = { 0x7dbea520, 0x3ec1, 0x11d2, { 0xa9, 0x8f, 0x00, 0xc0, 0x4f, 0x94, 0xa7, 0x17} }; DECLARE_MODULE_NAME("IRowChange"); DECLARE_MODULE_OWNER("Microsoft"); DECLARE_MODULE_DESCRIP("IRowChange interface test"); DECLARE_MODULE_VERSION(838086926); // TCW_WizardVersion(2) // TCW_Automation(False) // }} TCW_MODULE_GLOBALS_END ////////////////////////////////////////////////////////////////////////// // Globals // ////////////////////////////////////////////////////////////////////////// ULONG cInterfaceIIDs = 0; INTERFACEMAP* rgInterfaceIIDs = NULL; //-------------------------------------------------------------------- // @func Module level initialization routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems // BOOL ModuleInit(CThisTestModule * pThisTestModule) { //Obtain the Interface IIDs for the Row object if(GetInterfaceArray(ROW_INTERFACE, &cInterfaceIIDs, &rgInterfaceIIDs)) return CommonModuleInit(pThisTestModule, IID_IRowChange, SIZEOF_TABLE, ROW_INTERFACE); return FALSE; } //-------------------------------------------------------------------- // @func Module level termination routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems // BOOL ModuleTerminate(CThisTestModule * pThisTestModule) { return CommonModuleTerminate(pThisTestModule); } //////////////////////////////////////////////////////////////////////////// // TCIRowChange // //////////////////////////////////////////////////////////////////////////// class TCIRowChange : public CRowsetChange { public: //constructors TCIRowChange(WCHAR* pwszTestCaseName = INVALID(WCHAR*)); virtual ~TCIRowChange(); //methods virtual BOOL Init(); virtual BOOL Terminate(); //IRowChange virtual BOOL VerifySetColumns ( CRowObject* pCRowObject, DBCOUNTITEM iRow, DBORDINAL cColAccess, DBCOLUMNACCESS* rgColAccess ); virtual BOOL VerifySetColumns ( CRowObject* pCRowObject, DBCOUNTITEM iRow, ECOLS_BOUND eColsToBind = UPDATEABLE_NONINDEX_COLS_BOUND, BLOBTYPE dwBlobType = NO_BLOB_COLS, ECOLUMNORDER eBindingOrder = FORWARD, ECOLS_BY_REF eColsByRef = NO_COLS_BY_REF, DBTYPE dwModifier = DBTYPE_EMPTY, DBORDINAL cColsToBind = 0, DBORDINAL* rgColsToBind = NULL, DBPART dwPart = DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH ); virtual BOOL VerifySetColumnsAllRows ( CRowsetChange* pCRowset, ECOLS_BOUND eColsToBind = UPDATEABLE_NONINDEX_COLS_BOUND, BLOBTYPE dwBlobType = NO_BLOB_COLS, ECOLUMNORDER eBindingOrder = FORWARD, ECOLS_BY_REF eColsByRef = NO_COLS_BY_REF, DBTYPE dwModifier = DBTYPE_EMPTY, DBORDINAL cColsToBind = 0, DBORDINAL* rgColsToBind = NULL, DBPART dwPart = DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH ); //Thread Methods static ULONG WINAPI Thread_VerifySetColumns(LPVOID pv); //Interface virtual IRowChange* const pIRowChange(); //Data CRowObject* m_pCRowObject; IRowChange* m_pIRowChange; }; //////////////////////////////////////////////////////////////////////////// // TCIRowChange::TCIRowChange // //////////////////////////////////////////////////////////////////////////// TCIRowChange::TCIRowChange(WCHAR * wstrTestCaseName) : CRowsetChange(wstrTestCaseName) { m_pCRowObject = NULL; m_pIRowChange = NULL; } //////////////////////////////////////////////////////////////////////////// // TCIRowChange::~TCIRowChange // //////////////////////////////////////////////////////////////////////////// TCIRowChange::~TCIRowChange() { } //////////////////////////////////////////////////////////////////////////// // TCIRowChange::Init // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowChange::Init() { TBEGIN HROW hRow = NULL; //Create the new row object m_pCRowObject = new CRowObject; TESTC(m_pCRowObject != NULL); TESTC(CRowsetChange::Init()); //Create the Rowset object //CANHOLDROWS is a requireed level 0 property TESTC_(CreateRowset(DBPROP_CANHOLDROWS), S_OK); //Obtain the First row... TESTC_(GetNextRows(&hRow),S_OK); //Now create the row object. TEST2C_(m_pCRowObject->CreateRowObject(pIRowset(), hRow), S_OK, DB_S_NOROWSPECIFICCOLUMNS); //Now obtain our IRowChange interface. TESTC(VerifyInterface(m_pCRowObject->pIRow(), IID_IRowChange, ROW_INTERFACE, (IUnknown**)&m_pIRowChange)); CLEANUP: ReleaseRows(hRow); TRETURN } //////////////////////////////////////////////////////////////////////////// // TCIRowChange::Terminate // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowChange::Terminate() { SAFE_RELEASE(m_pIRowChange); SAFE_DELETE(m_pCRowObject); return CRowsetChange::Terminate(); } //////////////////////////////////////////////////////////////////////////// // TCIRowChange::VerifySetColumns // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowChange::VerifySetColumns ( CRowObject* pCRowObject, DBCOUNTITEM iRow, DBORDINAL cColAccess, DBCOLUMNACCESS* rgColAccess ) { TBEGIN HRESULT hr = S_OK; //Create the Data for SetColumns TESTC_(hr = pCRowObject->FillColAccess(pTable(), cColAccess, rgColAccess, iRow),S_OK); //IRowChange::SetColumns TESTC_(hr = pCRowObject->SetColumns(cColAccess, rgColAccess),S_OK); //IRow::GetColumns TESTC_(hr = pCRowObject->GetColumns(cColAccess, rgColAccess),S_OK); //Compare Data for this row object if(!pCRowObject->CompareColAccess(cColAccess, rgColAccess, iRow, pTable())) { //Data incorrect for this row! TERROR("Data was incorrect for row " << iRow); QTESTC(FALSE); } FreeColAccess(cColAccess, rgColAccess, FALSE); CLEANUP: TRETURN; } //////////////////////////////////////////////////////////////////////////// // TCIRowChange::VerifySetColumns // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowChange::VerifySetColumns ( CRowObject* pCRowObject, DBCOUNTITEM iRow, ECOLS_BOUND eColsToBind, BLOBTYPE dwBlobType, ECOLUMNORDER eBindingOrder, ECOLS_BY_REF eColsByRef, DBTYPE dwModifier, DBORDINAL cColsToBind, DBORDINAL* rgColsToBind, DBPART dwPart ) { TBEGIN HRESULT hr = S_OK; DBORDINAL cColAccess = 0; DBCOLUMNACCESS* rgColAccess = NULL; void* pData = NULL; //Create the ColAccess Structures... TESTC_(hr = pCRowObject->CreateColAccess(&cColAccess, &rgColAccess, &pData, NULL, eColsToBind, dwBlobType, eBindingOrder, eColsByRef, dwModifier, cColsToBind, rgColsToBind, dwPart),S_OK); //Verify SetColumns QTESTC(VerifySetColumns(pCRowObject, iRow, cColAccess, rgColAccess)); CLEANUP: TRETURN; } //////////////////////////////////////////////////////////////////////////// // TCIRowChange::VerifySetColumnsAllRows // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowChange::VerifySetColumnsAllRows ( CRowsetChange* pCRowset, ECOLS_BOUND eColsToBind, BLOBTYPE dwBlobType, ECOLUMNORDER eBindingOrder, ECOLS_BY_REF eColsByRef, DBTYPE dwModifier, DBORDINAL cColsToBind, DBORDINAL* rgColsToBind, DBPART dwPart ) { TBEGIN HRESULT hr = S_OK; DBCOUNTITEM iRow,cRowsObtained = 0; HROW* rghRows = NULL; CRowsetChange RowsetA; IRowsetUpdate* pIRowsetUpdate = NULL; //Restart the position. if(pCRowset) { TEST2C_(hr = pCRowset->RestartPosition(),S_OK, DB_E_CANNOTRESTART); } //Default rowset //Some providers may not be able to restart due to live data stream... if(pCRowset == NULL || hr==DB_E_CANNOTRESTART) { pCRowset = &RowsetA; //May require IRowsetLocate to position on Blobs if(dwBlobType != NO_BLOB_COLS) pCRowset->SetSettableProperty(DBPROP_IRowsetLocate); TESTC_(pCRowset->CreateRowset(),S_OK); } //See if we are in bufferred mode VerifyInterface(pCRowset->pIRowset(), IID_IRowsetUpdate, ROWSET_INTERFACE, (IUnknown**)&pIRowsetUpdate); //loop through the rowset, retrieve one row at a time for(iRow=1; iRow<=pCRowset->m_ulTableRows; iRow++) { //GetNextRow CRowObject RowObjectA; TESTC_(pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK); //Create the row object from this row TEST2C_(RowObjectA.CreateRowObject(pCRowset->pIRowset(), rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS); //Verify Row Object QTESTC(VerifySetColumns(&RowObjectA, iRow, eColsToBind, dwBlobType, eBindingOrder, eColsByRef, dwModifier, cColsToBind, rgColsToBind, dwPart)); //release the row handle TESTC_(pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK); PROVIDER_FREE(rghRows); //If the rowset is in buffered mode, it will require an Update, or Undo //before the change really takes effect. if(pIRowsetUpdate) TESTC_(pIRowsetUpdate->Update(NULL, 0, NULL, NULL, NULL, NULL),S_OK); } CLEANUP: if(pCRowset) pCRowset->ReleaseRows(cRowsObtained, rghRows); PROVIDER_FREE(rghRows); SAFE_RELEASE(pIRowsetUpdate); TRETURN } //////////////////////////////////////////////////////////////////////////// // TCIRowChange::Thread_VerifySetColumns // //////////////////////////////////////////////////////////////////////////// ULONG TCIRowChange::Thread_VerifySetColumns(void* pv) { THREAD_BEGIN //Thread Stack Variables TCIRowChange* pThis = (TCIRowChange*)THREAD_FUNC; CRowObject* pCRowObject = (CRowObject*)THREAD_ARG1; ASSERT(pThis && pCRowObject); ThreadSwitch(); //Let the other thread(s) catch up //IRowChange::SetColumns QTESTC(pThis->VerifySetColumns(pCRowObject, FIRST_ROW, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG)); ThreadSwitch(); //Let the other thread(s) catch up CLEANUP: THREAD_RETURN } //////////////////////////////////////////////////////////////////////////// // TCIRowChange::pIRowChange // //////////////////////////////////////////////////////////////////////////// IRowChange* const TCIRowChange::pIRowChange() { ASSERT(m_pIRowChange); return m_pIRowChange; } // {{ TCW_TEST_CASE_MAP(TCIRowChange_IUnknown) //*----------------------------------------------------------------------- // @class IRowChange IUnknown scenarios // class TCIRowChange_IUnknown : public TCIRowChange { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCIRowChange_IUnknown,TCIRowChange); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember IUnknown - QI Mandatory Interfaces int Variation_1(); // @cmember IUnknown - QI Optional Interfaces int Variation_2(); // @cmember IUnknown - AddRef / Release int Variation_3(); // }} TCW_TESTVARS_END } ; // {{ TCW_TESTCASE(TCIRowChange_IUnknown) #define THE_CLASS TCIRowChange_IUnknown BEG_TEST_CASE(TCIRowChange_IUnknown, TCIRowChange, L"IRowChange IUnknown scenarios") TEST_VARIATION(1, L"IUnknown - QI Mandatory Interfaces") TEST_VARIATION(2, L"IUnknown - QI Optional Interfaces") TEST_VARIATION(3, L"IUnknown - AddRef / Release") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCIRowChange_SetColumns) //*----------------------------------------------------------------------- // @class IRowChange::SetColumns // class TCIRowChange_SetColumns : public TCIRowChange { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCIRowChange_SetColumns,TCIRowChange); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember SetColumns - All columns - no BLOBs int Variation_1(); // @cmember SetColumns - All Columns - BLOBs int Variation_2(); // @cmember SetColumns - 0 columns - no-op int Variation_3(); // @cmember SetColumns - same column bound numerous times int Variation_4(); // @cmember SetColumns - BLOB Columns only int Variation_5(); // @cmember SetColumns - Each Column Seperatly int Variation_6(); // @cmember SetColumns - Asking for just Rowset columns int Variation_7(); // @cmember SetColumns - Asking for just Extra Row Columns int Variation_8(); // @cmember SetColumns - IUnknown Columns - native int Variation_9(); // @cmember Empty int Variation_10(); // @cmember SetColumns - Not Binding Value for all columns, pData is NULL - DB_E_ERRORSOCCURRED int Variation_11(); // @cmember SetColumns - Not Binding Value for some columns, pData is NULL - DB_S_ERRORSOCCURRED int Variation_12(); // @cmember SetColumns - Not Binding Value for ISNULL columns, pData is NULL - S_OK int Variation_13(); // @cmember SetColumns - Not Binding Value for BLOB columns, pData is NULL - S_OK int Variation_14(); // @cmember SetColumns - Binding all columns, even read-only columns - DB_S_ERRORSOCCURRED int Variation_15(); // @cmember Empty int Variation_16(); // @cmember Boundary - Some valid, some non-existent columns - DB_S_ERRORSOCCURRED int Variation_17(); // @cmember Boundary - All non-existent columns - DB_E_ERRORSOCCURRED int Variation_18(); // @cmember Boundary - No Vector Columns - S_OK int Variation_19(); // @cmember Boundary - No Vectors and Non-Existent Columns - DB_E_ERRORSOCCURRED int Variation_20(); // @cmember Boundary - Only Vector Columns - S_OK int Variation_21(); // @cmember Boundary - Only Non-Existent Vector Columns - DB_E_ERRORSOCCURRED int Variation_22(); // @cmember Boundary - Valid Vectors and Non-Existent Columns - DB_S_ERRORSOCCURRED int Variation_23(); // @cmember Boundary - Valid Non-Vectors and Non-Existent Vector Columns - DB_S_ERRORSOCCURRED int Variation_24(); // @cmember Empty int Variation_25(); // @cmember Status - DBSTATUS_S_ISNULL int Variation_26(); // @cmember Status - DBSTATUS_S_DEFAULT int Variation_27(); // @cmember Status - DBSTATUS_S_IGNORE int Variation_28(); // @cmember Empty int Variation_29(); // @cmember Buffered Mode - All Columns - no BLOBs int Variation_30(); // @cmember Buffered Mode - All Columns - BLOBs int Variation_31(); // @cmember Buffered Mode - All Columns - Just extra columns int Variation_32(); // @cmember Empty int Variation_33(); // @cmember Multiple Row Object - same row int Variation_34(); // @cmember Multiple Row Object - different rows int Variation_35(); // @cmember Empty int Variation_36(); // @cmember Threads - SetColumns seperate threads [same row object] int Variation_37(); // }} TCW_TESTVARS_END } ; // {{ TCW_TESTCASE(TCIRowChange_SetColumns) #define THE_CLASS TCIRowChange_SetColumns BEG_TEST_CASE(TCIRowChange_SetColumns, TCIRowChange, L"IRowChange::SetColumns") TEST_VARIATION(1, L"SetColumns - All columns - no BLOBs") TEST_VARIATION(2, L"SetColumns - All Columns - BLOBs") TEST_VARIATION(3, L"SetColumns - 0 columns - no-op") TEST_VARIATION(4, L"SetColumns - same column bound numerous times") TEST_VARIATION(5, L"SetColumns - BLOB Columns only") TEST_VARIATION(6, L"SetColumns - Each Column Seperatly") TEST_VARIATION(7, L"SetColumns - Asking for just Rowset columns") TEST_VARIATION(8, L"SetColumns - Asking for just Extra Row Columns") TEST_VARIATION(9, L"SetColumns - IUnknown Columns - native") TEST_VARIATION(10, L"Empty") TEST_VARIATION(11, L"SetColumns - Not Binding Value for all columns, pData is NULL - DB_E_ERRORSOCCURRED") TEST_VARIATION(12, L"SetColumns - Not Binding Value for some columns, pData is NULL - DB_S_ERRORSOCCURRED") TEST_VARIATION(13, L"SetColumns - Not Binding Value for ISNULL columns, pData is NULL - S_OK") TEST_VARIATION(14, L"SetColumns - Not Binding Value for BLOB columns, pData is NULL - S_OK") TEST_VARIATION(15, L"SetColumns - Binding all columns, even read-only columns - DB_S_ERRORSOCCURRED") TEST_VARIATION(16, L"Empty") TEST_VARIATION(17, L"Boundary - Some valid, some non-existent columns - DB_S_ERRORSOCCURRED") TEST_VARIATION(18, L"Boundary - All non-existent columns - DB_E_ERRORSOCCURRED") TEST_VARIATION(19, L"Boundary - No Vector Columns - S_OK") TEST_VARIATION(20, L"Boundary - No Vectors and Non-Existent Columns - DB_E_ERRORSOCCURRED") TEST_VARIATION(21, L"Boundary - Only Vector Columns - S_OK") TEST_VARIATION(22, L"Boundary - Only Non-Existent Vector Columns - DB_E_ERRORSOCCURRED") TEST_VARIATION(23, L"Boundary - Valid Vectors and Non-Existent Columns - DB_S_ERRORSOCCURRED") TEST_VARIATION(24, L"Boundary - Valid Non-Vectors and Non-Existent Vector Columns - DB_S_ERRORSOCCURRED") TEST_VARIATION(25, L"Empty") TEST_VARIATION(26, L"Status - DBSTATUS_S_ISNULL") TEST_VARIATION(27, L"Status - DBSTATUS_S_DEFAULT") TEST_VARIATION(28, L"Status - DBSTATUS_S_IGNORE") TEST_VARIATION(29, L"Empty") TEST_VARIATION(30, L"Buffered Mode - All Columns - no BLOBs") TEST_VARIATION(31, L"Buffered Mode - All Columns - BLOBs") TEST_VARIATION(32, L"Buffered Mode - All Columns - Just extra columns") TEST_VARIATION(33, L"Empty") TEST_VARIATION(34, L"Multiple Row Object - same row") TEST_VARIATION(35, L"Multiple Row Object - different rows") TEST_VARIATION(36, L"Empty") TEST_VARIATION(37, L"Threads - SetColumns seperate threads [same row object]") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCTransactions) //*----------------------------------------------------------------------- // @class IRowChange inside Transactions // class TCTransactions : public CTransaction { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCTransactions,CTransaction); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); //Helpers virtual BOOL VerifyTransaction(BOOL fCommit, BOOL fRetaining); // {{ TCW_TESTVARS() // @cmember ABORT with fRetaining TRUE int Variation_1(); // @cmember ABORT with fRetaining FALSE int Variation_2(); // @cmember COMMIT with fRetaining TRUE int Variation_3(); // @cmember COMMIT with fRetaining FALSE int Variation_4(); // }} TCW_TESTVARS_END } ; // {{ TCW_TESTCASE(TCTransactions) #define THE_CLASS TCTransactions BEG_TEST_CASE(TCTransactions, CTransaction, L"IRowChange inside Transactions") TEST_VARIATION(1, L"ABORT with fRetaining TRUE") TEST_VARIATION(2, L"ABORT with fRetaining FALSE") TEST_VARIATION(3, L"COMMIT with fRetaining TRUE") TEST_VARIATION(4, L"COMMIT with fRetaining FALSE") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Test Case Section // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // }} END_DECLARE_TEST_CASES() // {{ TCW_TESTMODULE(ThisModule) TEST_MODULE(3, ThisModule, gwszModuleDescrip) TEST_CASE(1, TCIRowChange_IUnknown) TEST_CASE(2, TCIRowChange_SetColumns) TEST_CASE(3, TCTransactions) END_TEST_MODULE() // }} TCW_TESTMODULE_END //////////////////////////////////////////////////////////////////////////// // TCTransactionsVerifyTransaction // //////////////////////////////////////////////////////////////////////////// BOOL TCTransactions::VerifyTransaction(BOOL fCommit, BOOL fRetaining) { HROW hRow; IGetRow* pIGetRow = NULL; BOOL fPreserving = FALSE; CRowset RowsetA; CRowObject RowObjectA; //start a transaction TESTC(StartTransaction(SELECT_ALLFROMTBL, (IUnknown**)&pIGetRow, 0, NULL)); TESTC_(RowsetA.CreateRowset(pIGetRow),S_OK); //Obtain a row object - before we commit/abort the transaction TESTC_(RowsetA.GetNextRows(&hRow),S_OK); TESTC_(RowObjectA.CreateRowObject(RowsetA.pIRowset(), hRow),S_OK); //FillColAccess (before we commit/abort the transaction TESTC_(RowObjectA.FillColAccess(RowsetA.pTable(), RowObjectA.m_cColAccess, RowObjectA.m_rgColAccess, FIRST_ROW),S_OK); //commit the transaction with fRetaining==TRUE if(fCommit) { TESTC(GetCommit(fRetaining)) fPreserving = m_fCommitPreserve; } else { TESTC(GetAbort(fRetaining)) fPreserving = m_fAbortPreserve; } if(fPreserving) { //fully functional //IRow::SetColumns TESTC(RowObjectA.SetColumns(RowObjectA.m_cColAccess, RowObjectA.m_rgColAccess)); //IRow::GetColumns TESTC_(RowObjectA.GetColumns(RowObjectA.m_cColAccess, RowObjectA.m_rgColAccess),S_OK); //Compare Data for this row object TESTC(RowObjectA.CompareColAccess(RowObjectA.m_cColAccess, RowObjectA.m_rgColAccess, FIRST_ROW, RowsetA.pTable())); } else { //zombie //IRow::SetColumns TESTC_(RowObjectA.SetColumns(RowObjectA.m_cColAccess, RowObjectA.m_rgColAccess),E_UNEXPECTED); } CLEANUP: SAFE_RELEASE(pIGetRow); //clean up. CleanUpTransaction(fRetaining ? S_OK : XACT_E_NOTRANSACTION); TRETURN } // {{ TCW_TC_PROTOTYPE(TCIRowChange_IUnknown) //*----------------------------------------------------------------------- //| Test Case: TCIRowChange_IUnknown - IRowChange IUnknown scenarios //| Created: 8/5/98 //*----------------------------------------------------------------------- //*----------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCIRowChange_IUnknown::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(TCIRowChange::Init()) // }} { return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc IUnknown - QI Mandatory Interfaces // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_IUnknown::Variation_1() { //Do some default IUnknown interface testing return DefaultObjectTesting(pIRowChange(), ROW_INTERFACE); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc IUnknown - QI Optional Interfaces // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_IUnknown::Variation_2() { //Do some default IUnknown interface testing return DefaultObjectTesting(pIRowChange(), ROW_INTERFACE); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc IUnknown - AddRef / Release // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_IUnknown::Variation_3() { //Do some default IUnknown interface testing return DefaultObjectTesting(pIRowChange(), ROW_INTERFACE); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCIRowChange_IUnknown::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(TCIRowChange::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCIRowChange_SetColumns) //*----------------------------------------------------------------------- //| Test Case: TCIRowChange_SetColumns - IRowChange::SetColumns //| Created: 8/5/98 //*----------------------------------------------------------------------- //*----------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCIRowChange_SetColumns::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(TCIRowChange::Init()) // }} { return TRUE; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc SetColumns - All columns - no BLOBs // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_1() { TBEGIN //Loop through all the rows in the rowset, verify the columns... TESTC(VerifySetColumnsAllRows(this, UPDATEABLE_NONINDEX_COLS_BOUND)); CLEANUP: TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc SetColumns - All Columns - BLOBs // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_2() { TBEGIN //Loop through all the rows in the rowset, verify the columns... TESTC(VerifySetColumnsAllRows(this, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG)); CLEANUP: TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc SetColumns - 0 columns - no-op // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_3() { TBEGIN //SetColumns - with (0 NULL) TESTC(VerifySetColumnsAllRows(this, USE_COLS_TO_BIND_ARRAY, BLOB_LONG, FORWARD, NO_COLS_BY_REF, DBTYPE_EMPTY, 0, NULL)); CLEANUP: TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc SetColumns - same column bound numerous times // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_4() { TBEGIN IColumnsInfo* pIColumnsInfo = NULL; DBORDINAL i,cColumns=0; DBCOLUMNINFO* rgColumnInfo = NULL; WCHAR* pStringBuffer = NULL; DBORDINAL cColOrds = 0; DBORDINAL* rgColOrds = NULL; //Use a new rowset, and ask for a non-forward-only cursor, //so we can obtain the data multiple times. CRowsetChange RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_OTHERUPDATEDELETE)==S_OK); //Get the ColumnInfo TESTC(VerifyInterface(pIRowChange(), IID_IColumnsInfo, ROW_INTERFACE, (IUnknown**)&pIColumnsInfo)); TESTC_(pIColumnsInfo->GetColumnInfo(&cColumns, &rgColumnInfo, &pStringBuffer),S_OK); SAFE_ALLOC(rgColOrds, DBORDINAL, cColumns); //Loop through each column seperatly... for(i=0; iGetColumnInfo(&cColumns, &rgColumnInfo, &pStringBuffer),S_OK); //Loop through each column seperatly... for(iCol=0; iColCreateColAccess(&cColAccess, &rgColAccess, &pData, NULL, ECOLS_BOUND(UPDATEABLE_NONINDEX_COLS_BOUND | NONNULLABLE_COLS_BOUND), NO_BLOB_COLS, FORWARD, NO_COLS_BY_REF, DBTYPE_EMPTY, 0, NULL, DBPART_LENGTH|DBPART_STATUS),S_OK); //FillColAccess //NOTE: We bound only the non-nullable columns, so we don't have to worry about //DBSTATUS_S_ISNULL passing, since value is not looked at... TESTC_(m_pCRowObject->FillColAccess(pTable(), cColAccess, rgColAccess, SECOND_ROW),S_OK); //IRowChange::SetColumns TESTC_(m_pCRowObject->SetColumns(cColAccess, rgColAccess), cColAccess ? DB_E_ERRORSOCCURRED : S_OK); //Verify Status' //Length only bindings for SetData/SetColumns are not allowed, (only for BLOBs) for(i=0; iCreateColAccess(&cColAccess, &rgColAccess, &pData, NULL, ECOLS_BOUND(UPDATEABLE_NONINDEX_COLS_BOUND | NONNULLABLE_COLS_BOUND), NO_BLOB_COLS),S_OK); //FillColAccess //NOTE: We bound only the non-nullable columns, so we don't have to worry about //DBSTATUS_S_ISNULL passing, since value is not looked at... TESTC_(m_pCRowObject->FillColAccess(pTable(), cColAccess, rgColAccess, SECOND_ROW),S_OK); //For some columns, don't bind the value for(i=0; iSetColumns(cColAccess, rgColAccess), cColAccess>1 ? DB_S_ERRORSOCCURRED : S_OK); //Make sure on output, that our pData's are unchanged! for(i=0; iCreateColAccess(&cColAccess, &rgColAccess, &pData, NULL, ECOLS_BOUND(UPDATEABLE_NONINDEX_COLS_BOUND | NULLABLE_COLS_BOUND), NO_BLOB_COLS, FORWARD, NO_COLS_BY_REF, DBTYPE_EMPTY, 0, NULL, DBPART_LENGTH|DBPART_STATUS),S_OK); //FillColAccess TESTC_(m_pCRowObject->FillColAccess(pTable(), cColAccess, rgColAccess, SECOND_ROW),S_OK); //Bind all columns as ISNULL (so the value is ignored) for(i=0; iSetColumns(cColAccess, rgColAccess), S_OK); //Verify all the columns (come back as ISNULL) TESTC_(m_pCRowObject->GetColumns(cColAccess, rgColAccess), S_OK); for(i=0; iVerifySetColumns(FIRST_ROW, pTable())); //Create the ColAccess Structures (for all columns - except index)... //NOTE: This includes any potentially readonly, or other non-updateable columns TESTC_(m_pCRowObject->CreateColAccess(&cColAccess, &rgColAccess, &pData, NULL, ECOLS_BOUND(NONINDEX_COLS_BOUND | NOBOOKMARK_COLS_BOUND)),S_OK); //FillColAccess //NOTE: We have to tell FillInputBindings to actually binding the readonly columns //since it normally just puts IGNORE in those places... TESTC_(m_pCRowObject->FillColAccess(pTable(), cColAccess, rgColAccess, SECOND_ROW, PRIMARY, NONINDEX_COLS_BOUND),S_OK); //IRowChange::SetColumns //NOTE: our helper verifies the hr to the status consensus... TEST3C_(hr = m_pCRowObject->SetColumns(cColAccess, rgColAccess), S_OK, DB_S_ERRORSOCCURRED, DB_E_ERRORSOCCURRED); //Verify all the columns for(i=0; ipIRow(), &pColAccess->columnid, 0, &dbColInfo, NULL)); //Now verify the data and status switch(pColAccess->dwStatus) { case DBSTATUS_S_OK: case DBSTATUS_S_ISNULL: //Verify the Data is CHANGED (should the the second row's data) TESTC_(m_pCRowObject->GetColumns(1, pColAccess), S_OK); TESTC(m_pCRowObject->CompareColAccess(1, pColAccess, SECOND_ROW, pTable())); //Make sure the column was updateable TESTC(dbColInfo.dwFlags & DBCOLUMNFLAGS_WRITE || dbColInfo.dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN); break; default: //Save the status before overwritting it with GetColumns DBSTATUS dbSetColumnsStatus = pColAccess->dwStatus; //Otherwise verify the data is UNCHANGED (should the the first row's data) TESTC_(m_pCRowObject->GetColumns(1, pColAccess), S_OK); if(dbColInfo.dwFlags & (DBCOLUMNFLAGS_ISROWID|DBCOLUMNFLAGS_ISROWVER)) { //For RowIDs we can't compare against original value since its altered on //on every setdata... } else { //Otherwise verify the data is UNCHANGED (should the the first row's data) if(!m_pCRowObject->CompareColAccess(1, pColAccess, FIRST_ROW, pTable())) TERROR("Data was incorrect for column (" << i << ")"); } if(dbSetColumnsStatus == DBSTATUS_E_PERMISSIONDENIED) TESTC(!(dbColInfo.dwFlags & DBCOLUMNFLAGS_WRITE || dbColInfo.dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)); //The only error we should be expecting for this senario is PERMISSIONDENIED. //We don't have a seperate case, since if some other error is returned for some //reason (a bug) its more important that the data is not updated (first) then //verification of the status takes second place... TESTC(dbSetColumnsStatus == DBSTATUS_E_PERMISSIONDENIED || dbSetColumnsStatus == DBSTATUS_E_UNAVAILABLE); break; }; } FreeColAccess(cColAccess, rgColAccess); CLEANUP: SAFE_FREE(pData); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_16() { return TEST_SKIPPED; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Boundary - Some valid, some non-existent columns - DB_S_ERRORSOCCURRED // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_17() { TBEGIN DBORDINAL cColAccess = 0; DBCOLUMNACCESS* rgColAccess = NULL; DBORDINAL cColAccess2 = 0; DBCOLUMNACCESS* rgColAccess2 = NULL; void* pData = NULL; void* pData2 = NULL; DBORDINAL cColInvalid = 0; DBCOLUMNACCESS* rgColInvalid = NULL; //Create the ColAccess Structures (for all columns)... //NOTE: We do this twice, since we want to test invalid columnid within valid ids. //A memcpy is not sufficient, since ColAccess contains ColIds which have to be allocated, //as well as memory location buffers, etc. Easier to just call twice... TESTC_(m_pCRowObject->CreateColAccess(&cColAccess, &rgColAccess, &pData, NULL, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG),S_OK); TESTC_(m_pCRowObject->CreateColAccess(&cColAccess2, &rgColAccess2, &pData2, NULL, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG),S_OK); //Now create complete ColAccess array, containing: //Format = 1 Invalid, All Valid, 2 Invalid, All Valid, 1 Invalid cColInvalid = 1 + cColAccess + 2 + cColAccess2 + 1; SAFE_ALLOC(rgColInvalid, DBCOLUMNACCESS, cColInvalid); //Create "Invalid" ColIDs memset(rgColInvalid, 0, (size_t)(sizeof(DBCOLUMNACCESS) * cColInvalid)); //Create First set of All Valid memcpy(&rgColInvalid[1], rgColAccess, (size_t)(sizeof(DBCOLUMNACCESS)*cColAccess)); //Create Second set of All Valid memcpy(&rgColInvalid[1 + cColAccess + 2], rgColAccess2, (size_t)(sizeof(DBCOLUMNACCESS)*cColAccess2)); //IRowChange::SetColumns TESTC_(m_pCRowObject->FillColAccess(pTable(), cColAccess, &rgColInvalid[1], SECOND_ROW),S_OK); TESTC_(m_pCRowObject->FillColAccess(pTable(), cColAccess2, &rgColInvalid[1 + cColAccess + 2], SECOND_ROW),S_OK); TESTC_(m_pCRowObject->SetColumns(cColInvalid, rgColInvalid),DB_S_ERRORSOCCURRED); //Verify Status' TESTC(rgColInvalid[0].dwStatus == DBSTATUS_E_DOESNOTEXIST); TESTC(rgColInvalid[1 + cColAccess + 0].dwStatus == DBSTATUS_E_DOESNOTEXIST); TESTC(rgColInvalid[1 + cColAccess + 1].dwStatus == DBSTATUS_E_DOESNOTEXIST); TESTC(rgColInvalid[1 + cColAccess + 2 + cColAccess2].dwStatus == DBSTATUS_E_DOESNOTEXIST); //Compare First All Valid Columns TESTC_(m_pCRowObject->GetColumns(cColAccess, &rgColInvalid[1]),S_OK); TESTC(m_pCRowObject->CompareColAccess(cColAccess, &rgColInvalid[1], SECOND_ROW, pTable())); //Compare Second All Valid Columns TESTC_(m_pCRowObject->GetColumns(cColAccess2, &rgColInvalid[1 + cColAccess + 2]),S_OK); TESTC(m_pCRowObject->CompareColAccess(cColAccess2, &rgColInvalid[1 + cColAccess + 2], SECOND_ROW, pTable())); FreeColAccess(cColAccess, rgColAccess); FreeColAccess(cColAccess2, rgColAccess2); CLEANUP: SAFE_FREE(pData); SAFE_FREE(pData2); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc Boundary - All non-existent columns - DB_E_ERRORSOCCURRED // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_18() { TBEGIN DBORDINAL i,cColInvalid = 0; DBCOLUMNACCESS* rgColInvalid = NULL; void* pData = NULL; //Create the ColAccess Structures (for all columns)... TESTC_(m_pCRowObject->CreateColAccess(&cColInvalid, &rgColInvalid, &pData, NULL, ALL_COLS_BOUND, BLOB_LONG),S_OK); //Now replace the Array with (unique/nonexistent) columns for(i=0; iSetColumns(cColInvalid, rgColInvalid),DB_E_ERRORSOCCURRED); //Verify Status' for(i=0; iCreateColAccess(&cColInvalid, &rgColInvalid, &pData, NULL, NOVECTOR_COLS_BOUND, BLOB_LONG),S_OK); //Now replace the Array with (unique/nonexistent) columns for(i=0; iSetColumns(cColInvalid, rgColInvalid),DB_E_ERRORSOCCURRED); //Verify Status' for(i=0; iCreateColAccess(&cColInvalid, &rgColInvalid, &pData, NULL, VECTOR_COLS_BOUND),S_OK); //Now replace the Array with (unique/nonexistent) columns for(i=0; iSetColumns(cColInvalid, rgColInvalid), cColInvalid ? DB_E_ERRORSOCCURRED : S_OK); //Verify Status' for(i=0; iCreateColAccess(&cColInvalid, &rgColInvalid, &pData, NULL, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG),S_OK); //Now for all non-vectors, create a new invalid colid for(i=0; iFillColAccess(pTable(), 1, &rgColInvalid[i], THIRD_ROW),S_OK); } else { TESTC_(CreateUniqueDBID(&rgColInvalid[i].columnid),S_OK); cNonVectors++; } } if(cColInvalid) hrExpected = (cColInvalid == cNonVectors) ? DB_E_ERRORSOCCURRED : DB_S_ERRORSOCCURRED; //IRowChange::SetColumns TESTC_(m_pCRowObject->SetColumns(cColInvalid, rgColInvalid), hrExpected); //Verify Status' for(i=0; iGetColumns(1, &rgColInvalid[i]),S_OK); TESTC(m_pCRowObject->CompareColAccess(1, &rgColInvalid[i], THIRD_ROW, pTable())); } else { //Only non-vectors where changed to non-existent columnids TESTC(rgColInvalid[i].dwStatus == DBSTATUS_E_DOESNOTEXIST); } } FreeColAccess(cColInvalid, rgColInvalid); CLEANUP: SAFE_FREE(pData); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(24) //*----------------------------------------------------------------------- // @mfunc Boundary - Valid Non-Vectors and Non-Existent Vector Columns - DB_S_ERRORSOCCURRED // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_24() { TBEGIN DBORDINAL i,cColInvalid = 0; DBCOLUMNACCESS* rgColInvalid = NULL; void* pData = NULL; ULONG cVectors = 0; HRESULT hrExpected = S_OK; //Create the ColAccess Structures (for all columns)... TESTC_(m_pCRowObject->CreateColAccess(&cColInvalid, &rgColInvalid, &pData, NULL, UPDATEABLE_NONINDEX_COLS_BOUND, NO_BLOB_COLS),S_OK); //Now for all non-vectors, create a new invalid colid for(i=0; iFillColAccess(pTable(), 1, &rgColInvalid[i], THIRD_ROW),S_OK); } } if(cColInvalid) hrExpected = (cColInvalid == cVectors) ? DB_E_ERRORSOCCURRED : DB_S_ERRORSOCCURRED; //IRowChange::SetColumns TESTC_(m_pCRowObject->SetColumns(cColInvalid, rgColInvalid), hrExpected); //Verify Status' for(i=0; iGetColumns(1, &rgColInvalid[i]),S_OK); TESTC(m_pCRowObject->CompareColAccess(1, &rgColInvalid[i], THIRD_ROW, pTable())); } } FreeColAccess(cColInvalid, rgColInvalid); CLEANUP: SAFE_FREE(pData); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(25) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_25() { return TEST_SKIPPED; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(26) //*----------------------------------------------------------------------- // @mfunc Status - DBSTATUS_S_ISNULL // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_26() { TBEGIN //ISNULL is tested basically for free. The privlib table, will contain a NULL diagonal, //or if using the INI file, somewhere within the file its pretty likely there is a NULL //value somewhere. This way we can just loop through all rows in the table and insert data //for that row to test SetColumns with a NULL value. //Loop through all the rows in the rowset, verify the columns... TESTC(VerifySetColumnsAllRows(this, UPDATEABLE_NONINDEX_COLS_BOUND)); CLEANUP: TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(27) //*----------------------------------------------------------------------- // @mfunc Status - DBSTATUS_S_DEFAULT // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_27() { //NOTE: This senario is already tested in the IRowsetChange test against //a provider that supports Row Objects it uses SetColumns under the covers so we don't //have to reinvent every new variation senario. //We could duplicate the senario just for completeness, but with the current time //constraints and the complexity of the verification we'll not duplciate efforts return TEST_SKIPPED; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(28) //*----------------------------------------------------------------------- // @mfunc Status - DBSTATUS_S_IGNORE // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_28() { //NOTE: This senario is already tested in the IRowsetChange test against //a provider that supports Row Objects it uses SetColumns under the covers so we don't //have to reinvent every new variation senario. //We could duplicate the senario just for completeness, but with the current time //constraints and the complexity of the verification we'll not duplciate efforts return TEST_SKIPPED; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(29) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_29() { return TEST_SKIPPED; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(30) //*----------------------------------------------------------------------- // @mfunc Buffered Mode - All Columns - no BLOBs // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_30() { TBEGIN //Create a buffered mode rowset CRowsetUpdate RowsetA; //Not all providers will support IRowsetUpdate TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Loop through all the rows in the rowset, verify the columns... TESTC(VerifySetColumnsAllRows(&RowsetA, UPDATEABLE_NONINDEX_COLS_BOUND)); CLEANUP: TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(31) //*----------------------------------------------------------------------- // @mfunc Buffered Mode - All Columns - BLOBs // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_31() { TBEGIN //Create a buffered mode rowset CRowsetUpdate RowsetA; //Not all providers will support IRowsetUpdate TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Loop through all the rows in the rowset, verify the columns... TESTC(VerifySetColumnsAllRows(&RowsetA, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG)); CLEANUP: TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(32) //*----------------------------------------------------------------------- // @mfunc Buffered Mode - All Columns - Just extra columns // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_32() { TBEGIN HRESULT hr = S_OK; DBORDINAL cColAccess = 0; DBCOLUMNACCESS* rgColAccess = NULL; void* pData = NULL; DBORDINAL cColumns = 0; DBORDINAL* rgColOrdinals = NULL; HROW hRow = NULL; //Create a buffered mode rowset CRowsetUpdate RowsetA; CRowObject RowObjectA; //Not all providers will support IRowsetUpdate TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the First row... TESTC_(RowsetA.GetNextRows(&hRow),S_OK); //Now create the row object. TEST2C_(RowObjectA.CreateRowObject(RowsetA.pIRowset(), hRow), S_OK, DB_S_NOROWSPECIFICCOLUMNS); //Obtain the just the Extra columns TESTC_(hr = RowObjectA.GetExtraColumnInfo(&cColumns, NULL, NULL, &rgColOrdinals),S_OK); //Create the ColAccess Structures for just the extra columns... TESTC_(hr = RowObjectA.CreateColAccess(&cColAccess, &rgColAccess, &pData, NULL, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG, FORWARD, NO_COLS_BY_REF, DBTYPE_EMPTY, cColumns, rgColOrdinals),S_OK); //Verify SetColumns TESTC(VerifySetColumns(&RowObjectA, FIRST_ROW, cColAccess, rgColAccess)); CLEANUP: FreeColAccess(cColAccess, rgColAccess); SAFE_FREE(pData); SAFE_FREE(rgColOrdinals); RowsetA.ReleaseRows(hRow); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(33) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_33() { return TEST_SKIPPED; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(34) //*----------------------------------------------------------------------- // @mfunc Multiple Row Object - same row // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_34() { TBEGIN HROW hRow = NULL; CRowsetChange RowsetA; CRowObject RowObjectA; CRowObject RowObjectB; //Create the rowset TESTC_(RowsetA.CreateRowset(),S_OK); //Obtain the First row... TESTC_(RowsetA.GetNextRows(&hRow),S_OK); //Now create the row object. TEST2C_(RowObjectA.CreateRowObject(RowsetA.pIRowset(), hRow), S_OK, DB_S_NOROWSPECIFICCOLUMNS); TESTC(VerifySetColumns(&RowObjectA, THIRD_ROW, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG)); //Now verify the data as seen from a new row object over the same row TEST2C_(RowObjectB.CreateRowObject(RowsetA.pIRowset(), hRow), S_OK, DB_S_NOROWSPECIFICCOLUMNS); TESTC(RowObjectB.VerifyGetColumns(THIRD_ROW, pTable(), UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG)); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(35) //*----------------------------------------------------------------------- // @mfunc Multiple Row Object - different rows // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_35() { TBEGIN HROW rghRows[TWO_ROWS]; CRowsetChange RowsetA; CRowObject RowObjectA; CRowObject RowObjectB; //Create the rowset TESTC_(RowsetA.CreateRowset(),S_OK); //Obtain the First row... TESTC_(RowsetA.GetNextRows(TWO_ROWS, rghRows),S_OK); //Now create the row objects. TEST2C_(RowObjectA.CreateRowObject(RowsetA.pIRowset(), rghRows[ROW_ONE]), S_OK, DB_S_NOROWSPECIFICCOLUMNS); TEST2C_(RowObjectB.CreateRowObject(RowsetA.pIRowset(), rghRows[ROW_TWO]), S_OK, DB_S_NOROWSPECIFICCOLUMNS); //Verify SetColumns (create and set data, using the third row data into this row) TESTC(VerifySetColumns(&RowObjectA, THIRD_ROW, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG)); TESTC(VerifySetColumns(&RowObjectB, FOURTH_ROW, UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG)); //Now verify the data as seen from a new row object over the same row TESTC(RowObjectB.VerifyGetColumns(FOURTH_ROW, pTable(), UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG)); TESTC(RowObjectA.VerifyGetColumns(THIRD_ROW, pTable(), UPDATEABLE_NONINDEX_COLS_BOUND, BLOB_LONG)); CLEANUP: RowsetA.ReleaseRows(TWO_ROWS, rghRows); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(36) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_36() { return TEST_SKIPPED; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(37) //*----------------------------------------------------------------------- // @mfunc Threads - SetColumns seperate threads [same row object] // // @rdesc TEST_PASS or TEST_FAIL // int TCIRowChange_SetColumns::Variation_37() { TBEGIN INIT_THREADS(MAX_THREADS); CRowsetChange RowsetA; CRowObject RowObjectA; HROW hRow = NULL; //Setup Thread Arguments THREADARG T1Arg = { this, &RowObjectA }; //Create Rowset object RowsetA.SetSettableProperty(DBPROP_IRowsetLocate); RowsetA.SetProperty(DBPROP_CANHOLDROWS); TESTC_(RowsetA.CreateRowset(),S_OK); //Obtain row object TESTC_(RowsetA.GetNextRows(&hRow),S_OK); TEST2C_(RowObjectA.CreateRowObject(RowsetA.pIRowset(), hRow),S_OK, DB_S_NOROWSPECIFICCOLUMNS); //Create Threads CREATE_THREADS(Thread_VerifySetColumns, &T1Arg); START_THREADS(); END_THREADS(); CLEANUP: TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCIRowChange_SetColumns::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(TCIRowChange::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCTransactions) //*----------------------------------------------------------------------- //| Test Case: TCTransactions - IRowChange inside Transactions //| Created: 8/5/98 //*----------------------------------------------------------------------- //*----------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCTransactions::Init() { if(CTransaction::Init()) { //register interface to be tested if(RegisterInterface(ROWSET_INTERFACE, IID_IGetRow, 0, NULL)) return TRUE; } //Not all providers have to support transactions //If a required interface, an error would have been posted by VerifyInterface TEST_PROVIDER(m_pITransactionLocal != NULL); return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc ABORT with fRetaining TRUE // // @rdesc TEST_PASS or TEST_FAIL // int TCTransactions::Variation_1() { return VerifyTransaction(FALSE/*fCommit*/, TRUE/*fRetaining*/); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc ABORT with fRetaining FALSE // // @rdesc TEST_PASS or TEST_FAIL // int TCTransactions::Variation_2() { return VerifyTransaction(FALSE/*fCommit*/, FALSE/*fRetaining*/); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc COMMIT with fRetaining TRUE // // @rdesc TEST_PASS or TEST_FAIL // int TCTransactions::Variation_3() { return VerifyTransaction(TRUE/*fCommit*/, TRUE/*fRetaining*/); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc COMMIT with fRetaining FALSE // // @rdesc TEST_PASS or TEST_FAIL // int TCTransactions::Variation_4() { return VerifyTransaction(TRUE/*fCommit*/, FALSE/*fRetaining*/); } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCTransactions::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CTransaction::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END