//+------------------------------------------------------------------------- // // 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; }