windows-nt/Source/XPSP1/NT/com/oleutest/cachetst/genenum.cpp
2020-09-26 16:20:57 +08:00

723 lines
15 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: genenum.cpp
//
// Contents: implementation of CEnumeratorTest object
// This is the object that does all of the testing.
//
// Classes:
//
// Functions:
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
//--------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
//+-------------------------------------------------------------------------
//
// Member: CEnumeratorTest::CEnumeratorTest
//
// Synopsis: constructor
//
// Arguments: none
//
// Returns:
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes:
//
//--------------------------------------------------------------------------
CEnumeratorTest::CEnumeratorTest()
{
m_pEnumTest = NULL;
m_ElementSize = 0;
m_ElementCount = -1;
}
//+-------------------------------------------------------------------------
//
// Member: CEnumeratorTest::CEnumeratorTest
//
// Synopsis: constructor
//
// Arguments: [enumtest] -- The enumerator object to be tested
// [elementsize] -- The size of one element from next
// [elementcount] -- The number of elements expected to in
// the enumerator. 0 if unknown.
//
// Returns:
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes:
//
//--------------------------------------------------------------------------
CEnumeratorTest::CEnumeratorTest(IGenEnum * enumtest, size_t elementsize, LONG elementcount)
{
m_pEnumTest = enumtest;
m_ElementSize = elementsize;
m_ElementCount = elementcount;
}
//+-------------------------------------------------------------------------
//
// Function: CEnumeratorTest::GetNext
//
// Synopsis: Internal Next Implementation. Does some basic checks on the
// return values.
//
// Effects:
//
// Arguments: [celt] -- the number of items to fetch
// [pceltFetched] -- the number of items fetched
// [phresult] -- the return from next
//
// Requires:
//
// Returns: True if the basic tests passed, false if they didn't
// The result of the next call itself is passed in param 3.
//
// Signals:
//
// Modifies:
//
// Algorithm: Checks:
// That if s_ok is returned celt and pceltFetched are ==
// If a verify is provided it is called
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes:
//
//--------------------------------------------------------------------------
BOOL CEnumeratorTest::GetNext( ULONG celt,
ULONG* pceltFetched,
HRESULT* phresult
)
{
void* prgelt;
ULONG ul;
BOOL fRet = TRUE;
//
// Allocate memory for the return elements
//
prgelt = new char[m_ElementSize * celt];
if (prgelt == NULL)
{
printf("IEnumX::GetNext out of memory.\r\n");
return(FALSE);
}
//
// Call next
//
*phresult = m_pEnumTest->Next(celt, prgelt, pceltFetched);
//
// If the return result is S_OK make sure the numbers match
//
if (*phresult == S_OK)
{
if ((pceltFetched) && (celt != *pceltFetched))
{
printf("IEnumX::Next returned S_OK but celt"
" and pceltFetch mismatch.\r\n");
fRet = FALSE;
}
}
//
// If false is returned then make sure celt is less than
// the number actually fetched
//
if (*phresult == S_FALSE)
{
if ((pceltFetched) && (celt < *pceltFetched))
{
printf("IEnumX::Next return S_FALSE but celt is"
" less than pceltFetch.\r\n");
fRet = FALSE;
}
}
//
// Call verify to make sure the elements are ok.
//
if ((*phresult == S_OK) || (*phresult == S_FALSE))
{
//
// If we got S_FALSE back set celt to the number of elements
// returned in pceltFetched. If the user gave NULL for
// pceltFetched and we got S_FALSE back then celt can only be
// zero.
//
if (*phresult == S_FALSE)
{
if (pceltFetched)
{
celt = *pceltFetched;
}
else
{
celt = 0;
}
}
//
// loop through every returned element
//
for (ul=0; ul <= celt ; ul++)
{
if ((fRet == TRUE) &&
(Verify(((char *)prgelt) + (ul * m_ElementSize)) == FALSE))
{
printf("Data element %d returned by IEnumX::Next is bad.\r\n", ul);
fRet = FALSE;
//
// we keep looping anyway just to
// free up resources.
//
}
//
// If the user supplied a cleanup function there is additional
// memory that needs to be freed
//
// Math: cast prgelt to char* to it a one byte size and then scale
// it by the index * the element size
//
Cleanup(((char *)prgelt) + (ul * m_ElementSize));
}
}
delete prgelt;
return fRet;
}
//+-------------------------------------------------------------------------
//
// Method: CEnumeratorTest::TestNext
//
// Synopsis: Test the next enumerator methods
//
// Effects:
//
// Arguments: None.
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes: BUGBUG: This function should really be broken down into
// smaller function.
// Also, the return mechanism is unwieldy.
//
//--------------------------------------------------------------------------
HRESULT CEnumeratorTest::TestNext(void)
{
ULONG celtFetched;
LONG lInternalCount = 0;
HRESULT hresult;
ULONG i;
void* prgelt;
//
// First we want to count the element by doing a next on each one.
//
do {
if (!GetNext(1, &celtFetched, &hresult))
{
return(E_FAIL);
}
if (hresult == S_OK)
{
lInternalCount++;
}
} while ( hresult == S_OK );
//
// If the user passed in an amount make sure it matches what we got
//
if ((m_ElementCount != -1) && (lInternalCount != m_ElementCount))
{
printf("IEnumX: enumerated count and passed count do not match!\r\n");
return(E_FAIL);
}
else if (m_ElementCount == -1)
{
//
// If the user didn't pass in the element count let's set it here.
//
m_ElementCount = lInternalCount;
}
hresult = m_pEnumTest->Reset();
if (hresult != S_OK)
{
printf("IEnumnX: Reset failed (%lx)\r\n", hresult );
return(E_FAIL);
}
//
// Make sure we fail on ...Next(celt>1, ...,NULL)
//
if (GetNext(2, NULL, &hresult))
{
if (SUCCEEDED(hresult))
{
printf("IEnumX: celt>1 pceltFetched==NULL returned success\r\n");
return(E_FAIL);
}
}
else
{
return(E_FAIL);
}
//
// This next test will call next getting more each time
//
for (i = 1; i < (ULONG)m_ElementCount; i++)
{
hresult = m_pEnumTest->Reset();
if (hresult != S_OK)
{
printf("IEnumnX: Reset failed (%lx)\r\n", hresult );
return(E_FAIL);
}
if (!GetNext(i, &celtFetched, &hresult))
{
return(E_FAIL);
}
if ((hresult != S_OK) || (celtFetched != i))
{
printf("IEnumX: next/reset test failed!\r\n");
return(E_FAIL);
}
}
//
// Now get more elements than we were supposed to
// This should return S_FALSE with the max number in the number fetched
//
hresult = m_pEnumTest->Reset();
if (hresult != S_OK)
{
printf("IEnumX: Reset failed (%lx)\r\n", hresult );
return(E_FAIL);
}
if (!GetNext(m_ElementCount + 1, &celtFetched, &hresult))
{
return(E_FAIL);
}
if ((hresult != S_FALSE) || (lInternalCount != m_ElementCount))
{
printf("IEnumX: next/reset test failed!\r\n");
return(E_FAIL);
}
//
// Now verifyall. We do it here after the object has been worked on a bit
// since it is more likely to fail at this point
//
hresult = m_pEnumTest->Reset();
if (hresult != S_OK)
{
printf("IEnumX: Reset failed (%lx)\r\n", hresult );
return(E_FAIL);
}
//
// Allocate memory for the return elements
//
prgelt = new char[m_ElementSize * m_ElementCount];
if (prgelt == NULL)
{
printf("IEnumX: verifyall new failed\r\n");
return(E_OUTOFMEMORY);
}
hresult = m_pEnumTest->Next(m_ElementCount, prgelt, &celtFetched);
if ((hresult != S_OK) || (celtFetched != (ULONG)m_ElementCount))
{
printf("IEnumX: verifyall test: next failed (%lx)\r\n", hresult );
delete prgelt;
return(E_FAIL);
}
if (VerifyAll(prgelt, m_ElementCount) == FALSE)
{
printf("IEnumX: verifyall failed (%lx)\r\n", hresult );
delete prgelt;
return(E_FAIL);
}
delete prgelt;
return(S_OK);
}
//+-------------------------------------------------------------------------
//
// Method: CEnumeratorTest::TestSkip
//
// Synopsis: This function calls all the tests
//
// Effects:
//
// Arguments: None
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes:
//
//--------------------------------------------------------------------------
HRESULT CEnumeratorTest::TestSkip(void)
{
LONG i;
HRESULT hresult;
ULONG celtFetched;
//
// Make sure we call TestNext to set the element count
//
if (m_ElementCount == -1)
{
TestNext();
}
//
// Call Skip, reset and try to get one element
//
for (i = 0; i < (LONG)m_ElementCount; i++)
{
hresult = m_pEnumTest->Reset();
if (hresult != S_OK)
{
printf("IEnumnX: Reset failed (%lx)\r\n", hresult );
return(E_FAIL);
}
hresult = m_pEnumTest->Skip(i);
if (hresult != S_OK)
{
printf("IEnumnX: Skip failed (%lx)\r\n", hresult );
return(E_FAIL);
}
//
// Now one element to provide some check that the skip worked
//
if (!GetNext(1, &celtFetched, &hresult))
{
return(E_FAIL);
}
if (hresult != S_OK)
{
return(E_FAIL);
}
}
//
// Reset the enumerator before we leave
//
hresult = m_pEnumTest->Reset();
if (hresult != S_OK)
{
printf("IEnumnX: Reset failed (%lx)\r\n", hresult );
return(E_FAIL);
}
return(S_OK);
}
//+-------------------------------------------------------------------------
//
// Method: CEnumeratorTest::TestRelease
//
// Synopsis: This function calls all the tests
//
// Effects:
//
// Arguments: None
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes:
//
//--------------------------------------------------------------------------
HRESULT CEnumeratorTest::TestRelease(void)
{
return(S_OK);
}
//+-------------------------------------------------------------------------
//
// Method: CEnumeratorTest::TestClone
//
// Synopsis: This function calls all the tests
//
// Effects:
//
// Arguments: None
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes:
//
//--------------------------------------------------------------------------
HRESULT CEnumeratorTest::TestClone(void)
{
return(S_OK);
}
//+-------------------------------------------------------------------------
//
// Method: CEnumeratorTest::TestAll
//
// Synopsis: This function calls all the tests
//
// Effects:
//
// Arguments: None
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes:
//
//--------------------------------------------------------------------------
HRESULT CEnumeratorTest::TestAll(void)
{
HRESULT hresult;
hresult = TestNext();
if (hresult == S_OK)
{
hresult = TestSkip();
}
if (hresult == S_OK)
{
hresult = TestClone();
}
if (hresult == S_OK)
{
hresult = TestRelease();
}
return(hresult);
}
//+-------------------------------------------------------------------------
//
// Method: CEnumeratorTest::VerifyAll
//
// Synopsis: Verify entire array of returned results.
//
// Arguments: None
//
// Returns: BOOL
//
// Algorithm: Just default to saying everything is ok
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes:
//
//--------------------------------------------------------------------------
BOOL CEnumeratorTest::VerifyAll(void *pv, LONG cl)
{
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Method: CEnumeratorTest::Verify
//
// Synopsis: Verify one element
//
// Arguments: None
//
// Returns: BOOL
//
// Algorithm: Just default to saying everything is ok
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
// Notes:
//
//--------------------------------------------------------------------------
BOOL CEnumeratorTest::Verify(void *pv)
{
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Method: CEnumeratorTest::Cleanup
//
// Synopsis: Default implementation of cleanup
//
// Arguments: [pv] - pointer to entry enumerated
//
// Algorithm: If there is nothing special to free this implementation
// can be used.
//
// History: dd-mmm-yy Author Comment
// 24-May-94 kennethm author
//
//--------------------------------------------------------------------------
void CEnumeratorTest::Cleanup(void *pv)
{
return;
}