2025-11-28 00:35:46 +09:00

2071 lines
52 KiB
C++

//--------------------------------------------------------------------
// Microsoft OLE DB Test
//
// Copyright (C) 1995-2000 Microsoft Corporation
//
// @doc
//
// @module IGetRow.cpp | This module tests the OLE DB IGetRow interface
//
#include "MODStandard.hpp" // Standard headers
#include "IGetRow.h" // IGetRow header
#include "ExtraLib.h"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Module Values
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// {{ TCW_MODULE_GLOBALS
DECLARE_MODULE_CLSID = { 0x910ec7b0, 0x2b1e, 0x11d2, { 0xa9, 0x8d, 0x00, 0xc0, 0x4f, 0x94, 0xa7, 0x17} };
DECLARE_MODULE_NAME("IGetRow");
DECLARE_MODULE_OWNER("Microsoft");
DECLARE_MODULE_DESCRIP("IGetRow interface test");
DECLARE_MODULE_VERSION(838086926);
// TCW_WizardVersion(2)
// TCW_Automation(False)
// }} TCW_MODULE_GLOBALS_END
//--------------------------------------------------------------------
// @func Module level initialization routine
//
// @rdesc Success or Failure
// @flag TRUE | Successful initialization
// @flag FALSE | Initialization problems
//
BOOL ModuleInit(CThisTestModule * pThisTestModule)
{
return CommonModuleInit(pThisTestModule, IID_IGetRow);
}
//--------------------------------------------------------------------
// @func Module level termination routine
//
// @rdesc Success or Failure
// @flag TRUE | Successful initialization
// @flag FALSE | Initialization problems
//
BOOL ModuleTerminate(CThisTestModule * pThisTestModule)
{
return CommonModuleTerminate(pThisTestModule);
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow
//
////////////////////////////////////////////////////////////////////////////
class TCIGetRow : public CRowset
{
public:
//constructors
TCIGetRow(WCHAR* pwszTestCaseName = INVALID(WCHAR*));
virtual ~TCIGetRow();
//methods
virtual BOOL Init();
virtual BOOL Terminate();
//Interface
virtual IGetRow* const pIGetRow();
//IGetRow::GetRowFromHROW
virtual BOOL VerifyGetRowFromHROW(DBCOUNTITEM cRows, HROW* rghRows, DBCOUNTITEM iRow, BOOL fGetURL = FALSE);
virtual BOOL VerifyGetRowFromAllRows();
//IGetRow::GetURLFromHROW
virtual BOOL VerifyGetURLFromHROW(DBCOUNTITEM cRows, HROW* rghRows, DBCOUNTITEM iRow);
virtual BOOL VerifyGetURLFromAllRows();
//Row Object
virtual BOOL VerifyRowObject(IUnknown* pIUnkRow, DBCOUNTITEM iRow);
//Thread Methods
static ULONG WINAPI Thread_VerifyGetFromHROW(LPVOID pv);
private:
//Data
IGetRow* m_pIGetRow;
};
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::TCIGetRow
//
////////////////////////////////////////////////////////////////////////////
TCIGetRow::TCIGetRow(WCHAR * wstrTestCaseName) : CRowset(wstrTestCaseName)
{
m_pIGetRow = NULL;
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::~TCIGetRow
//
////////////////////////////////////////////////////////////////////////////
TCIGetRow::~TCIGetRow()
{
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::Init
//
////////////////////////////////////////////////////////////////////////////
BOOL TCIGetRow::Init()
{
TBEGIN
TESTC(CRowset::Init());
//May require IRowsetLocate to position on Blobs
SetSettableProperty(DBPROP_IRowsetLocate);
SetProperty(DBPROP_CANHOLDROWS);
//Create the Rowset object
TESTC_(CreateRowset(), S_OK);
//Obtain the IGetRow interface
TESTC_(QI(pIRowset(), IID_IGetRow, (void**)&m_pIGetRow),S_OK);
CLEANUP:
TRETURN
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::Terminate
//
////////////////////////////////////////////////////////////////////////////
BOOL TCIGetRow::Terminate()
{
SAFE_RELEASE(m_pIGetRow);
return CRowset::Terminate();
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::pIGetRow
//
////////////////////////////////////////////////////////////////////////////
IGetRow* const TCIGetRow::pIGetRow()
{
ASSERT(m_pIGetRow);
return m_pIGetRow;
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::VerifyGetRowFromHROW
//
////////////////////////////////////////////////////////////////////////////
BOOL TCIGetRow::VerifyGetRowFromHROW
(
DBCOUNTITEM cRows,
HROW* rghRows,
DBCOUNTITEM iRow,
BOOL fGetURL
)
{
TBEGIN
IRow* pIRow = NULL;
//Obtain the row object.
for(DBCOUNTITEM i=0; i<cRows; i++)
{
if(fGetURL)
{
//NOTE: The helper verifies the URL returned
TESTC_(GetURLFromHROW(rghRows[i], NULL),S_OK);
}
else
{
TESTC_(GetRowFromHROW(NULL, rghRows[i], IID_IRow, (IUnknown**)&pIRow),S_OK);
//Verify this row object
TESTC(VerifyRowObject(pIRow, iRow + i));
SAFE_RELEASE(pIRow);
}
}
CLEANUP:
SAFE_RELEASE(pIRow);
TRETURN
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::VerifyGetURLFromHROW
//
////////////////////////////////////////////////////////////////////////////
BOOL TCIGetRow::VerifyGetURLFromHROW
(
DBCOUNTITEM cRows,
HROW* rghRows,
DBCOUNTITEM iRow
)
{
//Delegate (so we don't have to maintain two similar functions)
return VerifyGetRowFromHROW(cRows, rghRows, iRow, TRUE/*fGetURL*/);
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::VerifyGetRowFromAllRows
//
////////////////////////////////////////////////////////////////////////////
BOOL TCIGetRow::VerifyGetRowFromAllRows()
{
TBEGIN
DBCOUNTITEM i,cRowsObtained = 0;
HROW* rghRows = NULL;
//get the number of rows in the table
DBCOUNTITEM ulRowCount = pTable()->CountRowsOnTable();
//Make sure the cursor is at the start
TESTC_(RestartPosition(), S_OK);
//loop through the rowset, retrieve one row at a time
for(i=0; i<ulRowCount; i++)
{
//GetNextRow
TESTC_(GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK);
//IGetRow::GetRowFromHROW
TESTC(VerifyGetRowFromHROW(cRowsObtained, rghRows, i+1));
//release the row handle
TESTC_(ReleaseRows(cRowsObtained, rghRows),S_OK);
PROVIDER_FREE(rghRows);
}
CLEANUP:
ReleaseRows(cRowsObtained, rghRows);
PROVIDER_FREE(rghRows);
TRETURN
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::VerifyGetURLFromAllRows
//
////////////////////////////////////////////////////////////////////////////
BOOL TCIGetRow::VerifyGetURLFromAllRows()
{
TBEGIN
DBCOUNTITEM iRow,cRowsObtained = 0;
HROW* rghRows = NULL;
WCHAR** rgpwszURLs = NULL;
//get the number of rows in the table
DBCOUNTITEM ulRowCount = pTable()->CountRowsOnTable();
SAFE_ALLOC(rgpwszURLs, WCHAR*, ulRowCount);
memset(rgpwszURLs, 0, (size_t) (sizeof(WCHAR*)*ulRowCount));
//loop through the rowset, retrieve one row at a time
for(iRow=0; iRow<ulRowCount; iRow++)
{
//GetNextRows
TESTC_(GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK);
//IGetRow::GetURLFromHROW
TESTC_(GetURLFromHROW(rghRows[0], &rgpwszURLs[iRow]),S_OK);
TESTC(VerifyGetURLFromHROW(1, &rghRows[0], iRow+1));
//Make sure this URL is not the same as any of the
//previously returned URLs, (ie: to provide a URL back to this preticular row
//the URL must be unique - at least unique accross this rowset - all row different)
for(DBCOUNTITEM iPrev=0; iPrev<iRow; iPrev++)
{
TESTC(rgpwszURLs[iRow] && rgpwszURLs[iPrev]);
TESTC(wcscmp(rgpwszURLs[iRow], rgpwszURLs[iPrev])!=0);
}
//release the row handle
TESTC_(ReleaseRows(cRowsObtained, rghRows),S_OK);
PROVIDER_FREE(rghRows);
}
CLEANUP:
//Free all URLs...
for(iRow=0; iRow<ulRowCount; iRow++)
SAFE_FREE(rgpwszURLs[iRow]);
SAFE_FREE(rgpwszURLs);
ReleaseRows(cRowsObtained, rghRows);
PROVIDER_FREE(rghRows);
TRETURN
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::Thread_VerifyGetFromHROW
//
////////////////////////////////////////////////////////////////////////////
ULONG TCIGetRow::Thread_VerifyGetFromHROW(void* pv)
{
THREAD_BEGIN
//Thread Stack Variables
TCIGetRow* pThis = (TCIGetRow*)THREAD_FUNC;
ULONG cRows = (ULONG)THREAD_ARG1;
HROW* rghRows = (HROW*)THREAD_ARG2;
ULONG iRow = (ULONG)THREAD_ARG3;
BOOL fGetURL = (ULONG)THREAD_ARG4;
ASSERT(pThis && cRows && rghRows && iRow);
ThreadSwitch(); //Let the other thread(s) catch up
//IGetRow::GetRowFromHROW
TESTC(pThis->VerifyGetRowFromHROW(cRows, rghRows, iRow, fGetURL));
ThreadSwitch(); //Let the other thread(s) catch up
CLEANUP:
THREAD_RETURN
}
////////////////////////////////////////////////////////////////////////////
// TCIGetRow::VerifyRowObject
//
////////////////////////////////////////////////////////////////////////////
BOOL TCIGetRow::VerifyRowObject(IUnknown* pIUnkRow, DBCOUNTITEM iRow)
{
TBEGIN
CRowObject RowObject;
//Create our helper object
TESTC_(RowObject.SetRowObject(pIUnkRow),S_OK);
//Verify the data associated with the row object...
if(!RowObject.VerifyGetColumns(iRow, m_pTable, ALL_COLS_BOUND, BLOB_LONG))
{
//Data incorrect for this row!
TERROR("Row Object Data was incorrect for row " << iRow);
QTESTC(FALSE);
}
CLEANUP:
TRETURN
}
// {{ TCW_TEST_CASE_MAP(TCIGetRow_Unknown)
//*-----------------------------------------------------------------------
// @class IGetRow IUnknown testing
//
class TCIGetRow_Unknown : public TCIGetRow {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCIGetRow_Unknown,TCIGetRow);
// }} 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 - QI Invalid
int Variation_3();
// @cmember IUnknown - AddRef Release
int Variation_4();
// @cmember Empty
int Variation_5();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCIGetRow_Unknown)
#define THE_CLASS TCIGetRow_Unknown
BEG_TEST_CASE(TCIGetRow_Unknown, TCIGetRow, L"IGetRow IUnknown testing")
TEST_VARIATION(1, L"IUnknown - QI Mandatory interfaces")
TEST_VARIATION(2, L"IUnknown - QI Optional interfaces")
TEST_VARIATION(3, L"IUnknown - QI Invalid")
TEST_VARIATION(4, L"IUnknown - AddRef Release")
TEST_VARIATION(5, L"Empty")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCIGetRow_GetRowFromHROW)
//*-----------------------------------------------------------------------
// @class IGetRow::GetRowFromHROW testing
//
class TCIGetRow_GetRowFromHROW : public TCIGetRow {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCIGetRow_GetRowFromHROW,TCIGetRow);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember General - Get row object for every row
int Variation_1();
// @cmember General - Get row multiple times for same row
int Variation_2();
// @cmember General - Get row over different rows from the rowset
int Variation_3();
// @cmember Empty
int Variation_4();
// @cmember Empty
int Variation_5();
// @cmember Aggregation - non-IUnknown
int Variation_6();
// @cmember Aggregation - Agg IUnknown
int Variation_7();
// @cmember Aggregation - Agg Row -> GetSourceRowset
int Variation_8();
// @cmember Aggregation - Agg Rowset -> Row -> GetSourceRowset
int Variation_9();
// @cmember Empty
int Variation_10();
// @cmember riid - IOpenRowset with IID_IGetRow
int Variation_11();
// @cmember riid - Execute with IID_IGetRow
int Variation_12();
// @cmember Empty
int Variation_13();
// @cmember Properties - DBPROP_IGetRow - IOpenRowset
int Variation_14();
// @cmember Properties - DBPROP_IGetRow - Execute
int Variation_15();
// @cmember Empty
int Variation_16();
// @cmember Properties - CANHOLDROWS = TRUE - obtain multiple rows with outstanding row objects
int Variation_17();
// @cmember Properties - CANHOLDROWS = FALSE - try to obtain multiple rows with outstanding row objects
int Variation_18();
// @cmember Empty
int Variation_19();
// @cmember Threads - GetRowFromHROW
int Variation_20();
// @cmember Empty
int Variation_21();
// @cmember Boundary - DB_E_DELETEDROW
int Variation_22();
// @cmember Boundary - DB_E_DELETEDROW - Bufferred Mode
int Variation_23();
// @cmember Empty
int Variation_24();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCIGetRow_GetRowFromHROW)
#define THE_CLASS TCIGetRow_GetRowFromHROW
BEG_TEST_CASE(TCIGetRow_GetRowFromHROW, TCIGetRow, L"IGetRow::GetRowFromHROW testing")
TEST_VARIATION(1, L"General - Get row object for every row")
TEST_VARIATION(2, L"General - Get row multiple times for same row")
TEST_VARIATION(3, L"General - Get row over different rows from the rowset")
TEST_VARIATION(4, L"Empty")
TEST_VARIATION(5, L"Empty")
TEST_VARIATION(6, L"Aggregation - non-IUnknown")
TEST_VARIATION(7, L"Aggregation - Agg IUnknown")
TEST_VARIATION(8, L"Aggregation - Agg Row -> GetSourceRowset")
TEST_VARIATION(9, L"Aggregation - Agg Rowset -> Row -> GetSourceRowset")
TEST_VARIATION(10, L"Empty")
TEST_VARIATION(11, L"riid - IOpenRowset with IID_IGetRow")
TEST_VARIATION(12, L"riid - Execute with IID_IGetRow")
TEST_VARIATION(13, L"Empty")
TEST_VARIATION(14, L"Properties - DBPROP_IGetRow - IOpenRowset")
TEST_VARIATION(15, L"Properties - DBPROP_IGetRow - Execute")
TEST_VARIATION(16, L"Empty")
TEST_VARIATION(17, L"Properties - CANHOLDROWS = TRUE - obtain multiple rows with outstanding row objects")
TEST_VARIATION(18, L"Properties - CANHOLDROWS = FALSE - try to obtain multiple rows with outstanding row objects")
TEST_VARIATION(19, L"Empty")
TEST_VARIATION(20, L"Threads - GetRowFromHROW")
TEST_VARIATION(21, L"Empty")
TEST_VARIATION(22, L"Boundary - DB_E_DELETEDROW")
TEST_VARIATION(23, L"Boundary - DB_E_DELETEDROW - Bufferred Mode")
TEST_VARIATION(24, L"Empty")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCIGetRow_GetURLFromHROW)
//*-----------------------------------------------------------------------
// @class IGetRow::GetURLFomHROW testing
//
class TCIGetRow_GetURLFromHROW : public TCIGetRow {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCIGetRow_GetURLFromHROW,TCIGetRow);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember General - Obtain URL for every row in the rowset - verify all different URLs
int Variation_1();
// @cmember General - Obtain for the same row - verify same URL but different string pointers
int Variation_2();
// @cmember Empty
int Variation_3();
// @cmember Boundary - E_INVALIDARG
int Variation_4();
// @cmember Empty
int Variation_5();
// @cmember Threads - GetURLFromHROW from seperate threads
int Variation_6();
// @cmember Empty
int Variation_7();
// @cmember Boundary - DB_E_DELETEDROW - Immediate mode
int Variation_8();
// @cmember Boundary - DB_E_DELETEDROW - Buffered mode
int Variation_9();
// @cmember Empty
int Variation_10();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCIGetRow_GetURLFromHROW)
#define THE_CLASS TCIGetRow_GetURLFromHROW
BEG_TEST_CASE(TCIGetRow_GetURLFromHROW, TCIGetRow, L"IGetRow::GetURLFomHROW testing")
TEST_VARIATION(1, L"General - Obtain URL for every row in the rowset - verify all different URLs")
TEST_VARIATION(2, L"General - Obtain for the same row - verify same URL but different string pointers")
TEST_VARIATION(3, L"Empty")
TEST_VARIATION(4, L"Boundary - E_INVALIDARG")
TEST_VARIATION(5, L"Empty")
TEST_VARIATION(6, L"Threads - GetURLFromHROW from seperate threads")
TEST_VARIATION(7, L"Empty")
TEST_VARIATION(8, L"Boundary - DB_E_DELETEDROW - Immediate mode")
TEST_VARIATION(9, L"Boundary - DB_E_DELETEDROW - Buffered mode")
TEST_VARIATION(10, L"Empty")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCTransactions)
//*-----------------------------------------------------------------------
// @class Transaction senarios
//
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"Transaction senarios")
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(4, ThisModule, gwszModuleDescrip)
TEST_CASE(1, TCIGetRow_Unknown)
TEST_CASE(2, TCIGetRow_GetRowFromHROW)
TEST_CASE(3, TCIGetRow_GetURLFromHROW)
TEST_CASE(4, TCTransactions)
END_TEST_MODULE()
// }} TCW_TESTMODULE_END
////////////////////////////////////////////////////////////////////////////
// TCTransactionsVerifyTransaction
//
////////////////////////////////////////////////////////////////////////////
BOOL TCTransactions::VerifyTransaction(BOOL fCommit, BOOL fRetaining)
{
HROW hRow;
CRowset RowsetA;
IGetRow* pIGetRow = NULL;
IRow* pIRow = NULL;
WCHAR* pwszURL = NULL;
BOOL fPreserving = FALSE;
//start a transaction
TESTC(StartTransaction(USE_SUPPORTED_SELECT_ALLFROMTBL, (IUnknown**)&pIGetRow, 0, NULL));
TESTC_(RowsetA.CreateRowset(pIGetRow),S_OK);
//Obtain a row handle - before we commit/abort the transaction
TESTC_(RowsetA.GetNextRows(&hRow),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
//GetRowFromHROW
TEST2C_(pIGetRow->GetRowFromHROW(NULL, hRow, IID_IRow, (IUnknown**)&pIRow), S_OK, DB_S_NOROWSPECIFICCOLUMNS);
TESTC(pIRow != NULL);
TESTC(DefaultObjectTesting(pIRow, ROW_INTERFACE));
//GetURLFromHROW
TESTC_(pIGetRow->GetURLFromHROW(hRow, &pwszURL), S_OK);
TESTC(pwszURL != NULL);
}
else
{
//zombie
//GetRowFromHROW
TESTC_(pIGetRow->GetRowFromHROW(NULL, hRow, IID_IRow, (IUnknown**)&pIRow), E_UNEXPECTED);
TESTC(pIRow == NULL);
//GetURLFromHROW
TESTC_(pIGetRow->GetURLFromHROW(hRow, &pwszURL), E_UNEXPECTED);
TESTC(pwszURL == NULL);
}
CLEANUP:
SAFE_RELEASE(pIGetRow);
SAFE_RELEASE(pIRow);
SAFE_FREE(pwszURL);
//clean up.
CleanUpTransaction(fRetaining ? S_OK : XACT_E_NOTRANSACTION);
TRETURN
}
// {{ TCW_TC_PROTOTYPE(TCIGetRow_Unknown)
//*-----------------------------------------------------------------------
//| Test Case: TCIGetRow_Unknown - IGetRow IUnknown testing
//| Created: 8/24/98
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCIGetRow_Unknown::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCIGetRow::Init())
// }}
{
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc IUnknown - QI Mandatory interfaces
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_Unknown::Variation_1()
{
//Do some default IUnknown interface testing
return DefaultObjectTesting(pIGetRow(), ROWSET_INTERFACE);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc IUnknown - QI Optional interfaces
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_Unknown::Variation_2()
{
//Do some default IUnknown interface testing
return DefaultObjectTesting(pIGetRow(), ROWSET_INTERFACE);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc IUnknown - QI Invalid
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_Unknown::Variation_3()
{
TBEGIN
//Do some invalid testing of IUnknown
//NOTE: Our helper (QI) veries the result pointer...
TESTC_(QI(pIGetRow(), IID_IRow), E_NOINTERFACE); //Row
TESTC_(QI(pIGetRow(), IID_ICommand), E_NOINTERFACE); //Session
TESTC_(QI(pIGetRow(), IID_IOpenRowset), E_NOINTERFACE); //Session
TESTC_(QI(pIGetRow(), IID_IDBProperties), E_NOINTERFACE); //DataSource
TESTC_(QI(pIGetRow(), IID_ISourcesRowset), E_NOINTERFACE); //Enumerator
TESTC_(QI(pIGetRow(), IID_IBindResource), E_NOINTERFACE); //Binder
TESTC_(QI(pIGetRow(), IID_ISequentialStream), E_NOINTERFACE); //Stream
TESTC_(QI(pIGetRow(), IID_IRowPosition), E_NOINTERFACE); //RowPosition
TESTC_(QI(pIGetRow(), IID_IRowsetNotify), E_NOINTERFACE); //ConnectionPoint
TESTC_(QI(pIGetRow(), IID_IDBAsynchNotify), E_NOINTERFACE); //ConnectionPoint
TESTC_(QI(pIGetRow(), IID_IDataInitialize), E_NOINTERFACE); //ServiceComponents
TESTC_(QI(pIGetRow(), IID_IDBPromptInitialize), E_NOINTERFACE); //DataLinks
//Note: DefaultObjectTesting (above) covers numerous senarios, it covers
//IID_NULL, NULL output pointer, etc...
CLEANUP:
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc IUnknown - AddRef Release
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_Unknown::Variation_4()
{
//Do some default IUnknown interface testing
return DefaultObjectTesting(pIGetRow(), ROWSET_INTERFACE);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_Unknown::Variation_5()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCIGetRow_Unknown::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCIGetRow::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCIGetRow_GetRowFromHROW)
//*-----------------------------------------------------------------------
//| Test Case: TCIGetRow_GetRowFromHROW - IGetRow::GetRowFromHROW testing
//| Created: 8/24/98
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCIGetRow_GetRowFromHROW::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCIGetRow::Init())
// }}
{
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc General - Get row object for every row
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_1()
{
TBEGIN
//Get the row object for every row and verify
TESTC(VerifyGetRowFromAllRows());
CLEANUP:
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc General - Get row multiple times for same row
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_2()
{
TBEGIN
HROW hRow = NULL;
IRow* pIRow = NULL;
IColumnsInfo* pIColumnsInfo = NULL;
//Obtain the second row
TESTC_(GetRow(SECOND_ROW, &hRow),S_OK);
//Get the row object for this row
TESTC(VerifyGetRowFromHROW(ONE_ROW, &hRow, SECOND_ROW));
//Obtain and verify this row object again
TESTC(VerifyGetRowFromHROW(ONE_ROW, &hRow, SECOND_ROW));
//Obtain the row object and leave open...
TESTC_(GetRowFromHROW(NULL, hRow, IID_IRow, (IUnknown**)&pIRow),S_OK);
TESTC_(GetRowFromHROW(NULL, hRow, IID_IColumnsInfo, (IUnknown**)&pIColumnsInfo),S_OK);
//Verify the row object...
TESTC(VerifyRowObject(pIRow, SECOND_ROW));
TESTC(VerifyRowObject(pIColumnsInfo, SECOND_ROW));
CLEANUP:
ReleaseRows(hRow);
SAFE_RELEASE(pIRow);
SAFE_RELEASE(pIColumnsInfo);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc General - Get row over different rows from the rowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_3()
{
TBEGIN
HROW hRow = NULL;
IRow* pIRow = NULL;
IColumnsInfo* pIColumnsInfo = NULL;
//Obtain the second row
TESTC_(GetRow(SECOND_ROW, &hRow),S_OK);
TESTC_(GetRowFromHROW(NULL, hRow, IID_IRow, (IUnknown**)&pIRow),S_OK);
ReleaseRows(hRow);
//Obtain the third row
TESTC_(GetNextRows(&hRow),S_OK);
TESTC_(GetRowFromHROW(NULL, hRow, IID_IColumnsInfo, (IUnknown**)&pIColumnsInfo),S_OK);
ReleaseRows(hRow);
//Verify the row objects...
TESTC(VerifyRowObject(pIRow, SECOND_ROW));
TESTC(VerifyRowObject(pIColumnsInfo, THIRD_ROW));
CLEANUP:
ReleaseRows(hRow);
SAFE_RELEASE(pIRow);
SAFE_RELEASE(pIColumnsInfo);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_4()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_5()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Aggregation - non-IUnknown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_6()
{
TBEGIN
HROW hRow = NULL;
CAggregate Aggregate(pIRowset());
IUnknown* pIUnkInner = INVALID(IUnknown*); //Make sure pointer is NULLed on error
//Obtain the second row
TESTC_(GetRow(SECOND_ROW, &hRow),S_OK);
//Try to obtain anything but IID_IUnknown.
//This should fail, this is a requirement for COM Aggregation...
TESTC_(GetRowFromHROW(&Aggregate, hRow, IID_IRow, (IUnknown**)&pIUnkInner), DB_E_NOAGGREGATION);
CLEANUP:
ReleaseRows(hRow);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Aggregation - Agg IUnknown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_7()
{
TBEGIN
HROW hRow = NULL;
CAggregate Aggregate(pIRowset());
IUnknown* pIUnkInner = NULL;
HRESULT hr = S_OK;
//Obtain the second row
TESTC_(GetRow(SECOND_ROW, &hRow),S_OK);
//Aggregation
hr = GetRowFromHROW(&Aggregate, hRow, IID_IUnknown, &pIUnkInner);
Aggregate.SetUnkInner(pIUnkInner);
//Verify Aggregation...
TESTC_PROVIDER(Aggregate.VerifyAggregationQI(hr, IID_IRow));
CLEANUP:
ReleaseRows(hRow);
SAFE_RELEASE(pIUnkInner);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Aggregation - Agg Row -> GetSourceRowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_8()
{
TBEGIN
HROW hRow = NULL;
CAggregate Aggregate(pIRowset());
HRESULT hr = S_OK;
IRow* pIRow = NULL;
IGetRow* pIGetRow = INVALID(IGetRow*);
IUnknown* pIUnkInner = NULL;
//Obtain the second row
TESTC_(GetRow(SECOND_ROW, &hRow),S_OK);
//Aggregation
hr = GetRowFromHROW(&Aggregate, hRow, IID_IUnknown, &pIUnkInner);
Aggregate.SetUnkInner(pIUnkInner);
//Verify Aggregation...
TESTC_PROVIDER(Aggregate.VerifyAggregationQI(hr, IID_IRow, (IUnknown**)&pIRow));
//GetSourceRowset (invalid interface)
TESTC_(hr = pIRow->GetSourceRowset(IID_IAggregate, (IUnknown**)&pIGetRow, NULL),E_NOINTERFACE);
TESTC(pIGetRow == NULL);
//GetSourceRowset (valid interface)
TEST2C_(hr = pIRow->GetSourceRowset(IID_IGetRow, (IUnknown**)&pIGetRow, NULL),S_OK,DB_E_NOSOURCEOBJECT);
TESTC(DefaultObjectTesting(pIGetRow, ROWSET_INTERFACE));
CLEANUP:
SAFE_RELEASE(pIRow);
if(pIGetRow != INVALID(IGetRow*))
SAFE_RELEASE(pIGetRow);
ReleaseRows(hRow);
SAFE_RELEASE(pIUnkInner);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Aggregation - Agg Rowset -> Row -> GetSourceRowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_9()
{
TBEGIN
HROW hRow = NULL;
CAggregate Aggregate(pIRowset());
IRow* pIRow = NULL;
IGetRow* pIGetRow = NULL;
IUnknown* pIAggregate = NULL;
COpenRowset OpenRowsetA;
CRowset RowsetA;
IUnknown* pIUnkInner = NULL;
ULONG ulRefCountBefore, ulRefCountAfter;
//Create a rowset that is Aggregated...
HRESULT hr = OpenRowsetA.CreateOpenRowset(IID_IUnknown, (IUnknown**)&pIUnkInner, &Aggregate);
Aggregate.SetUnkInner(pIUnkInner);
//Verify Aggregation for this rowset...
TESTC_PROVIDER(Aggregate.VerifyAggregationQI(hr, IID_IGetRow, (IUnknown**)&pIGetRow));
//Obtain the second row
TESTC_(RowsetA.CreateRowset(pIGetRow),S_OK);
TESTC_(RowsetA.GetRow(SECOND_ROW, &hRow),S_OK);
//Now Create the Row (non-aggregated)
ulRefCountBefore = Aggregate.GetRefCount();
TEST2C_(hr = pIGetRow->GetRowFromHROW(NULL, hRow, IID_IRow, (IUnknown**)&pIRow),S_OK,DB_S_NOROWSPECIFICCOLUMNS);
ulRefCountAfter = Aggregate.GetRefCount();
//IRow::GetSourceRow
TEST2C_(hr = pIRow->GetSourceRowset(IID_IAggregate, (IUnknown**)&pIAggregate, NULL),S_OK,DB_E_NOSOURCEOBJECT);
if(hr==S_OK)
{
TESTC(VerifyEqualInterface(pIAggregate, pIGetRow));
//Verify the child correctly addref'd the parent outer.
//The is an absolute requirement that the child keep the parent outer alive.
//If it doesn't addref the outer, the outer can be released externally since
//its not being used anymore due to the fact the outer controls the refcount
//of the inner. Many providers incorrectly addref the inner, which does nothing
//but guareentee the inner survives, but the inner will delegate to the outer
//and crash since it no longer exists...
TCOMPARE_(ulRefCountAfter > ulRefCountBefore);
}
else
{
TWARNING(L"IRow::GetSourceRowset unable to retrieve Parent object!");
}
CLEANUP:
SAFE_RELEASE(pIAggregate);
SAFE_RELEASE(pIRow);
SAFE_RELEASE(pIGetRow);
ReleaseRows(hRow);
SAFE_RELEASE(pIUnkInner);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_10()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc riid - IOpenRowset with IID_IGetRow
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_11()
{
TBEGIN
IGetRow* pIGetRow = NULL;
//Create a row object from IOpenRowset
TESTC_(pTable()->CreateRowset(USE_OPENROWSET, IID_IGetRow, 0, NULL, (IUnknown**)&pIGetRow),S_OK);
TESTC(DefaultObjectTesting(pIGetRow, ROWSET_INTERFACE));
CLEANUP:
SAFE_RELEASE(pIGetRow);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc riid - Execute with IID_IGetRow
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_12()
{
TBEGIN
IGetRow* pIGetRow = NULL;
//Create a row object from IOpenRowset
TESTC_(pTable()->CreateRowset(SELECT_ALLFROMTBL, IID_IGetRow, 0, NULL, (IUnknown**)&pIGetRow),S_OK);
TESTC(DefaultObjectTesting(pIGetRow, ROWSET_INTERFACE));
CLEANUP:
SAFE_RELEASE(pIGetRow);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_13()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Properties - DBPROP_IGetRow - IOpenRowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_14()
{
TBEGIN
IUnknown* pIUnknown = NULL;
ULONG cPropSets = 0;
DBPROPSET* rgPropSets = NULL;
//DBPROP_IGetRow
::SetProperty(DBPROP_IGetRow, DBPROPSET_ROWSET, &cPropSets, &rgPropSets);
//Create a row object from IOpenRowset asking for IID_IUnknown and DBPROP_IGetRow.
TESTC_(pTable()->CreateRowset(USE_OPENROWSET, IID_IUnknown, cPropSets, rgPropSets, &pIUnknown),S_OK);
//Verify a Rowset object is returned...
TESTC(DefaultObjectTesting(pIUnknown, ROWSET_INTERFACE));
CLEANUP:
SAFE_RELEASE(pIUnknown);
::FreeProperties(&cPropSets, &rgPropSets);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Properties - DBPROP_IGetRow - Execute
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_15()
{
TBEGIN
IUnknown* pIUnknown = NULL;
ULONG cPropSets = 0;
DBPROPSET* rgPropSets = NULL;
//DBPROP_IGetRow
::SetProperty(DBPROP_IGetRow, DBPROPSET_ROWSET, &cPropSets, &rgPropSets);
//Create a row object from ICommand::Execute asking for IID_IUnknown and DBPROP_IGetRow
TESTC_(pTable()->CreateRowset(SELECT_ALLFROMTBL, IID_IUnknown, cPropSets, rgPropSets, &pIUnknown),S_OK);
//Verify a Rowset object is returned...
TESTC(DefaultObjectTesting(pIUnknown, ROWSET_INTERFACE));
CLEANUP:
SAFE_RELEASE(pIUnknown);
::FreeProperties(&cPropSets, &rgPropSets);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_16()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Properties - CANHOLDROWS = TRUE - obtain multiple rows with outstanding row objects
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_17()
{
TBEGIN
DBCOUNTITEM iRow,ulRowCount = 0;
HROW hRow = NULL;
IUnknown** rgpIUnk = NULL;
IGetRow* pIGetRow = NULL;
CRowset RowsetA;
//Create the rowset
RowsetA.SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, (void*)VARIANT_TRUE);
RowsetA.SetSettableProperty(DBPROP_IRowsetLocate);
TESTC_(RowsetA.CreateRowset(),S_OK);
TESTC_(QI(RowsetA.pIRowset(), IID_IGetRow, (void**)&pIGetRow),S_OK);
//get the number of rows in the table
ulRowCount = pTable()->CountRowsOnTable();
SAFE_ALLOC(rgpIUnk, IUnknown*, ulRowCount);
memset(rgpIUnk, 0, (size_t) (sizeof(IUnknown*)*ulRowCount));
//RestartPosition
TESTC_(RowsetA.RestartPosition(),S_OK);
//loop through the rowset, retrieve one row at a time
for(iRow=0; iRow<ulRowCount; iRow++)
{
//GetNextRow
TESTC_(RowsetA.GetNextRows(&hRow),S_OK);
//IGetRow::GetRowFromHROW
TEST2C_(pIGetRow->GetRowFromHROW(NULL, hRow, IID_IUnknown, &rgpIUnk[iRow]),S_OK,DB_S_NOROWSPECIFICCOLUMNS);
TESTC(VerifyRowObject(rgpIUnk[iRow], iRow+1));
//Make sure this row object is not the same as any of the
//previously returned row object pointers
for(DBCOUNTITEM iPrev=0; iPrev<iRow; iPrev++)
TESTC(!VerifyEqualInterface(rgpIUnk[iRow], rgpIUnk[iPrev]));
//release the row handle
TESTC_(RowsetA.ReleaseRows(hRow),S_OK);
}
CLEANUP:
//Release all the row objects...
for(iRow=0; iRow<ulRowCount; iRow++)
SAFE_RELEASE(rgpIUnk[iRow]);
SAFE_FREE(rgpIUnk);
RowsetA.ReleaseRows(hRow);
SAFE_RELEASE(pIGetRow);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Properties - CANHOLDROWS = FALSE - try to obtain multiple rows with outstanding row objects
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_18()
{
TBEGIN
DBCOUNTITEM iRow,ulRowCount = 0;
HROW hRow = NULL;
IUnknown** rgpIUnk = NULL;
IGetRow* pIGetRow = NULL;
CRowset RowsetA;
HRESULT hr = S_OK;
//Create the rowset
RowsetA.SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, (void*)VARIANT_FALSE);
RowsetA.SetSettableProperty(DBPROP_IRowsetLocate);
TESTC_(RowsetA.CreateRowset(),S_OK);
TESTC_(QI(RowsetA.pIRowset(), IID_IGetRow, (void**)&pIGetRow),S_OK);
//get the number of rows in the table
ulRowCount = pTable()->CountRowsOnTable();
SAFE_ALLOC(rgpIUnk, IUnknown*, ulRowCount);
memset(rgpIUnk, 0, (size_t) (sizeof(IUnknown*)*ulRowCount));
//RestartPosition
TESTC_(RowsetA.RestartPosition(),S_OK);
//loop through the rowset, retrieve one row at a time
for(iRow=0; iRow<ulRowCount; iRow++)
{
//GetNextRow
//TODO: Spec issue
//An outstanding row object may keep a refcount on the rowset row handle
//so even though the consumer has released all refcounts the user may not
//be able to obtain another row handle.
TEST2C_(hr = RowsetA.GetNextRows(&hRow),S_OK,DB_E_ROWSNOTRELEASED);
//May need work if the provider cannot support obtaining more rows
//while their is an outstanding row object...
if(FAILED(hr))
{
//We should at least be able to obtain the first row (without error)
TESTC(iRow != 0);
//Make sure we can obtain the row once all outstanding row objects
//are released. To do this we will just release our list and
//continue with the fall through verification logic
for(DBCOUNTITEM iPrev=0; iPrev<iRow; iPrev++)
SAFE_RELEASE(rgpIUnk[iPrev]);
//Now we should be able to obtain another row handle
TESTC_(hr = RowsetA.GetNextRows(&hRow),S_OK);
}
//IGetRow::GetRowFromHROW
TEST2C_(pIGetRow->GetRowFromHROW(NULL, hRow, IID_IUnknown, &rgpIUnk[iRow]),S_OK,DB_S_NOROWSPECIFICCOLUMNS);
TESTC(VerifyRowObject(rgpIUnk[iRow], iRow+1));
//Make sure this row object is not the same as any of the
//previously returned row object pointers
for(DBCOUNTITEM iPrev=0; iPrev<iRow; iPrev++)
TESTC(!VerifyEqualInterface(rgpIUnk[iRow], rgpIUnk[iPrev]));
//release the row handle
TESTC_(RowsetA.ReleaseRows(hRow),S_OK);
}
CLEANUP:
//Release all the row objects...
for(iRow=0; iRow<ulRowCount; iRow++)
SAFE_RELEASE(rgpIUnk[iRow]);
SAFE_FREE(rgpIUnk);
RowsetA.ReleaseRows(hRow);
SAFE_RELEASE(pIGetRow);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_19()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Threads - GetRowFromHROW
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_20()
{
TBEGIN
INIT_THREADS(MAX_THREADS);
DBCOUNTITEM cRowsObtained = 0;
HROW rghRows[FIVE_ROWS];
HRESULT hr = S_OK;
//Setup Thread Arguments
THREADARG T1Arg = { this, (void*)FIVE_ROWS, rghRows, (void*)FIRST_ROW, FALSE/*fGetURL*/ };
//Get the first five rows
TEST2C_(hr = GetRow(FIRST_ROW, FIVE_ROWS, &cRowsObtained, rghRows), S_OK, DB_S_ROWLIMITEXCEEDED);
T1Arg.pArg1 = (void*)cRowsObtained;
//Create Threads
CREATE_THREADS(Thread_VerifyGetFromHROW, &T1Arg);
START_THREADS();
END_THREADS();
CLEANUP:
ReleaseRows(cRowsObtained, rghRows);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_21()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc Boundary - DB_E_DELETEDROW
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_22()
{
TBEGIN
HROW hRow = NULL;
CRowsetChange RowsetA;
CRowObject RowObjectA;
IRow* pIRow = NULL;
//Create a new rowset, (this requires IRowsetChange)
TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK);
//Delete the first row handle
TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK);
TESTC_(RowsetA.DeleteRow(hRow),S_OK);
//DB_E_DELETEDROW - Now call GetRowFromHROW on a deleted row handle
//NOTE: The helper verifies both the positive and negative output params...
TESTC_(RowObjectA.CreateRowObject(RowsetA.pIRowset(), hRow), DB_E_DELETEDROW);
CLEANUP:
ReleaseRows(hRow);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(23)
//*-----------------------------------------------------------------------
// @mfunc Boundary - DB_E_DELETEDROW - Bufferred Mode
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_23()
{
TBEGIN
HROW hRow = NULL;
CRowsetUpdate RowsetA;
CRowObject RowObjectA;
IRow* pIRow = NULL;
//Create a new rowset, (this requires IRowsetUpdate)
TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK);
//Delete the first row handle
TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK);
TESTC_(RowsetA.DeleteRow(hRow),S_OK);
//DB_E_DELETEDROW - Now call GetRowFromHROW on a deleted row handle
//NOTE: The helper verifies both the positive and negative output params...
TESTC_(RowObjectA.CreateRowObject(RowsetA.pIRowset(), hRow), DB_E_DELETEDROW);
//Update the pending change
TESTC_(RowsetA.UpdateRow(hRow),S_OK);
TESTC_(RowObjectA.CreateRowObject(RowsetA.pIRowset(), hRow), DB_E_DELETEDROW);
CLEANUP:
ReleaseRows(hRow);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetRowFromHROW::Variation_24()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCIGetRow_GetRowFromHROW::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCIGetRow::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCIGetRow_GetURLFromHROW)
//*-----------------------------------------------------------------------
//| Test Case: TCIGetRow_GetURLFromHROW - IGetRow::GetURLFomHROW testing
//| Created: 8/18/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCIGetRow_GetURLFromHROW::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCIGetRow::Init())
// }}
{
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc General - Obtain URL for every row in the rowset - verify all different URLs
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_1()
{
TBEGIN
//Get the row object for every row and verify
TESTC(VerifyGetURLFromAllRows());
CLEANUP:
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc General - Obtain for the same row - verify same URL but different string pointers
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_2()
{
TBEGIN
HROW hRow1 = NULL;
HROW hRow2 = NULL;
WCHAR* pwszURL1 = NULL;
WCHAR* pwszURL2 = NULL;
//Obtain the thrid row URL
TESTC_(GetRow(THIRD_ROW, &hRow1),S_OK);
TESTC_(GetURLFromHROW(hRow1, &pwszURL1),S_OK);
//Obtain another row (in between - just to mess it up)
TESTC_(GetRow(SECOND_ROW, &hRow2),S_OK);
TESTC_(GetURLFromHROW(hRow2, &pwszURL2),S_OK);
TESTC(wcscmp(pwszURL1, pwszURL2)!=0);
SAFE_FREE(pwszURL2);
//Now Obtain the thrid row URL (again)
TESTC_(GetRow(THIRD_ROW, &hRow2),S_OK);
TESTC_(GetURLFromHROW(hRow2, &pwszURL2),S_OK);
//Verify URLs are the same - but different string pointers
TESTC(wcscmp(pwszURL1, pwszURL2)==0);
TESTC(pwszURL1 != pwszURL2);
CLEANUP:
SAFE_FREE(pwszURL1);
SAFE_FREE(pwszURL2);
ReleaseRows(hRow1);
ReleaseRows(hRow2);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_3()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Boundary - E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_4()
{
TBEGIN
HROW hRow = NULL;
//Obtain the first row handle
//NOTE: Even for this invalidarg senario we still have to send in a "good"
//row handle since the provider is not required to valid that param (for performance
//reasons), and may actually use it before validating the other required one...
TESTC_(GetRow(FIFTH_ROW, &hRow),S_OK);
//NOTE: We have to call the method directory since our helper
//automatically supplies the output pointer if neccessary
TESTC_(pIGetRow()->GetURLFromHROW(hRow, NULL), E_INVALIDARG);
CLEANUP:
ReleaseRows(hRow);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_5()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Threads - GetURLFromHROW from seperate threads
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_6()
{
TBEGIN
INIT_THREADS(MAX_THREADS);
DBCOUNTITEM cRowsObtained = 0;
HROW rghRows[FIVE_ROWS];
HRESULT hr = S_OK;
//Setup Thread Arguments
THREADARG T1Arg = { this, (void*)FIVE_ROWS, rghRows, (void*)FIRST_ROW, (void*)TRUE/*fGetURL*/ };
//Get the first five rows
TEST2C_(hr = GetRow(FIRST_ROW, FIVE_ROWS, &cRowsObtained, rghRows), S_OK, DB_S_ROWLIMITEXCEEDED);
T1Arg.pArg1 = (void*)cRowsObtained;
//Create Threads
CREATE_THREADS(Thread_VerifyGetFromHROW, &T1Arg);
START_THREADS();
END_THREADS();
CLEANUP:
ReleaseRows(cRowsObtained, rghRows);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_7()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Boundary - DB_E_DELETEDROW - Immediate mode
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_8()
{
TBEGIN
HROW hRow = NULL;
CRowsetChange RowsetA;
WCHAR* pwszURL = NULL;
//Create a new rowset, (this requires IRowsetChange)
TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK);
//Delete the first row handle
TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK);
TESTC_(RowsetA.DeleteRow(hRow),S_OK);
//DB_E_DELETEDROW - Now call GetURLFromHROW on a deleted row handle
//NOTE: This helper takes care of validating arguments...
TESTC_(RowsetA.GetURLFromHROW(hRow, &pwszURL), DB_E_DELETEDROW);
CLEANUP:
ReleaseRows(hRow);
SAFE_FREE(pwszURL);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Boundary - DB_E_DELETEDROW - Buffered mode
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_9()
{
TBEGIN
HROW hRow = NULL;
CRowsetUpdate RowsetA;
WCHAR* pwszURL = NULL;
//Create a new rowset, (this requires IRowsetUpdate)
TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK);
//Delete the first row handle
TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK);
TESTC_(RowsetA.DeleteRow(hRow),S_OK);
//DB_E_DELETEDROW - Now call GetURLFromHROW on a deleted row handle
//NOTE: This helper takes care of validating arguments...
TESTC_(RowsetA.GetURLFromHROW(hRow, &pwszURL), DB_E_DELETEDROW);
//Update the pending change
TESTC_(RowsetA.UpdateRow(hRow),S_OK);
TESTC_(RowsetA.GetURLFromHROW(hRow, &pwszURL), DB_E_DELETEDROW);
CLEANUP:
ReleaseRows(hRow);
SAFE_FREE(pwszURL);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Empty
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCIGetRow_GetURLFromHROW::Variation_10()
{
return TEST_SKIPPED;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCIGetRow_GetURLFromHROW::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCIGetRow::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCTransactions)
//*-----------------------------------------------------------------------
//| Test Case: TCTransactions - Transaction senarios
//| Created: 8/24/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(FALSE/*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