/*++ Copyright (c) 2000 Microsoft Corporation Module Name: TestIWiaEnumXXX.cpp Abstract: Author: Hakki T. Bostanci (hakkib) 06-Apr-2000 Revision History: --*/ #include "stdafx.h" // // This is not a real .cpp module, it is meant to be included in .h // #ifdef DEFINE_TEMPLATES ////////////////////////////////////////////////////////////////////////// // // // template struct storage_traits { }; template <> struct storage_traits > { typedef CIWiaPropertyStoragePtr storage_type; }; template <> struct storage_traits > { typedef CWiaDevCap storage_type; }; template <> struct storage_traits > { typedef CWiaFormatInfo storage_type; }; template <> struct storage_traits > { typedef CIWiaItemPtr storage_type; }; template <> struct storage_traits > { typedef CStatPropStg storage_type; }; ////////////////////////////////////////////////////////////////////////// // // // template void TestEnum(interface_type &pEnum, PCTSTR pInterfaceName) { m_pszContext = pInterfaceName; TestGetCount(pEnum); TestReset(pEnum); TestNext(pEnum); TestSkip(pEnum); TestClone(pEnum); m_pszContext = 0; } ////////////////////////////////////////////////////////////////////////// // // // template void TestNext(interface_type &pEnum) { typedef storage_traits::storage_type storage_type; ULONG nItems = -1; CHECK_HR(pEnum->GetCount(&nItems)); if (nItems == 0) { return; } // try to get items; first, last, all, one more than all, past the last SubTestNext(pEnum, 0, 1, 1, S_OK); SubTestNext(pEnum, nItems-1, 1, 1, S_OK); SubTestNext(pEnum, 0, nItems, nItems, S_OK); SubTestNext(pEnum, 0, nItems+1, nItems, S_FALSE); SubTestNext(pEnum, nItems-1, 2, 1, S_FALSE); //SubTestNext(pEnum, nItems, 1, 0, S_FALSE); //SubTestNext(pEnum, 0, nItems, UINT_MAX, nItems); // try to pass 0 for celtFetched, // this should be allowed when fetching one item CHECK_HR(pEnum->Reset()); CCppMem pOneItem(1); LOG_HR(pEnum->Next(1, &pOneItem[0], 0), == S_OK); if (m_bRunBadParamTests) { // try to pass 0 for celtFetched, // this should not be allowed when fetching more than one item CHECK_HR(pEnum->Reset()); CCppMem pTwoItems(2); LOG_HR(pEnum->Next(2, &pTwoItems[0], 0), != S_OK); // try to pass 0 for the element array // this should not be allowed CHECK_HR(pEnum->Reset()); ULONG nFetched = -1; LOG_HR(pEnum->Next(0, 0, &nFetched), != S_OK); } } ////////////////////////////////////////////////////////////////////////// // // // template void SubTestNext( interface_type &pEnum, ULONG nToBeSkipped, ULONG nAskedToBeFetched, ULONG nExpectedToBeFetched, HRESULT hrExpected ) { typedef storage_traits::storage_type storage_type; CHECK_HR(pEnum->Reset()); if (nToBeSkipped) { CHECK_HR(pEnum->Skip(nToBeSkipped)); } CCppMem pItems(nAskedToBeFetched); ULONG nFetched = -1; HRESULT hrAPI = pEnum->Next(nAskedToBeFetched, &pItems[0], &nFetched); if (hrAPI != hrExpected) { LOG_ERROR( _T("pEnum->Next(%d, &pItems[0], &nFetched) == %s, expected %s"), nAskedToBeFetched, (PCTSTR) HResultToStr(hrAPI), (PCTSTR) HResultToStr(hrExpected) ); } LOG_CMP(nFetched, ==, nExpectedToBeFetched); } ////////////////////////////////////////////////////////////////////////// // // // template void TestReset(interface_type &pEnum) { typedef storage_traits::storage_type storage_type; ULONG nItems = -1; CHECK_HR(pEnum->GetCount(&nItems)); if (nItems == 0) { return; } // reset and read the first element CHECK_HR(pEnum->Reset()); if (!m_bBVTMode) { storage_type FirstItemBeforeQueryingAll; CHECK_HR(pEnum->Next(1, &FirstItemBeforeQueryingAll, 0)); // go to the last item HRESULT hr; do { storage_type Item; hr = pEnum->Next(1, &Item, 0); } while (hr == S_OK); // reset the enumerator and read the first element again CHECK_HR(pEnum->Reset()); storage_type FirstItemAfterQueryingAll; CHECK_HR(pEnum->Next(1, &FirstItemAfterQueryingAll, 0)); if (FirstItemBeforeQueryingAll != FirstItemAfterQueryingAll) { LOG_ERROR(_T("FirstItemBeforeQueryingAll != FirstItemAfterQueryingAll")); } } } ////////////////////////////////////////////////////////////////////////// // // // template void TestSkip(interface_type &pEnum) { typedef storage_traits::storage_type storage_type; // get the item count ULONG nItems = -1; CHECK_HR(pEnum->GetCount(&nItems)); if (nItems == 0) { return; } // read and store each item CHECK_HR(pEnum->Reset()); CCppMem pItems(nItems); for (int i = 0; i < nItems; ++i) { CHECK_HR(pEnum->Next(1, &pItems[i], 0)); } // test valid cases for (int nToBeSkipped = 0; nToBeSkipped < nItems; ++nToBeSkipped) { CHECK_HR(pEnum->Reset()); for (int nItem = nToBeSkipped; nItem < nItems; nItem += nToBeSkipped + 1) { CHECK_HR(pEnum->Skip(nToBeSkipped)); storage_type Item; CHECK_HR(pEnum->Next(1, &Item, 0)); if (Item != pItems[nItem]) { LOG_ERROR(_T("Item != pItems[nItem] after skipping %d"), nToBeSkipped); } } } // test invalid cases if (m_bRunBadParamTests) { CHECK_HR(pEnum->Reset()); LOG_HR(pEnum->Skip(nItems+1), == S_FALSE); CHECK_HR(pEnum->Reset()); LOG_HR(pEnum->Skip(-1), == S_FALSE); } } ////////////////////////////////////////////////////////////////////////// // // // template void TestClone(interface_type &pEnum, bool bRecurse = true) { typedef storage_traits::storage_type storage_type; // make the clone interface_type pClone; if (LOG_HR(pEnum->Clone(&pClone), == S_OK) && !m_bBVTMode) { // reset both the original and the clone enumerators, then iterate // through each element one by one and compare them CHECK_HR(pEnum->Reset()); CHECK_HR(pClone->Reset()); HRESULT hr, hr1, hr2; while (1) { // also, make a clone of the current state and check that // the state is captured in the clone interface_type pClone2; CHECK_HR(pEnum->Clone(&pClone2)); // get the next item from the original interface storage_type Item; hr = pEnum->Next(1, &Item, 0); // get the next item from the first clone storage_type Item1; hr1 = pClone->Next(1, &Item1, 0); // get the next item from the second clone storage_type Item2; hr2 = pClone2->Next(1, &Item2, 0); if (hr != S_OK || hr1 != S_OK || hr2 != S_OK) { break; } if (Item != Item1 || Item1 != Item2) { LOG_ERROR(_T("Clone states are not equal")); } } if (hr != S_FALSE || hr1 != S_FALSE || hr2 != S_FALSE) { LOG_ERROR(_T("After enumeration, clone states are not equal")); } // test the clone TestNext(pClone); TestReset(pClone); TestSkip(pClone); if (bRecurse) { TestClone(pClone, false); } TestGetCount(pClone); } // test bad param if (m_bRunBadParamTests) { LOG_HR(pEnum->Clone(0), != S_OK); } } ////////////////////////////////////////////////////////////////////////// // // // template void TestGetCount(interface_type &pEnum) { typedef storage_traits::storage_type storage_type; // First, get the item count using GetCount() ULONG cItemsFromGetCount = 0; if (LOG_HR(pEnum->GetCount(&cItemsFromGetCount), == S_OK) && !m_bBVTMode) { // Now, find the item count by first resetting the enumerator // and then querying for each item one by one using Next() ULONG cItemsFromNext = 0; CHECK_HR(pEnum->Reset()); HRESULT hr; do { // verify that GetCount returns the same result after a Next or Reset ULONG cItemsFromGetCountNow = 0; LOG_HR(pEnum->GetCount(&cItemsFromGetCountNow), == S_OK); LOG_CMP(cItemsFromGetCountNow, ==, cItemsFromGetCount); // get the next item storage_type Item; ULONG cFetched = 0; hr = pEnum->Next(1, &Item, &cFetched); cItemsFromNext += cFetched; } while (hr == S_OK); LOG_HR(hr, == S_FALSE); // verify that the two counts are equal LOG_CMP(cItemsFromNext, ==, cItemsFromGetCount); } // test bad param if (m_bRunBadParamTests) { LOG_HR(pEnum->GetCount(0), != S_OK); } } #endif //DEFINE_TEMPLATES