Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

441 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. TestIWiaEnumXXX.cpp
  5. Abstract:
  6. Author:
  7. Hakki T. Bostanci (hakkib) 06-Apr-2000
  8. Revision History:
  9. --*/
  10. #include "stdafx.h"
  11. //
  12. // This is not a real .cpp module, it is meant to be included in .h
  13. //
  14. #ifdef DEFINE_TEMPLATES
  15. //////////////////////////////////////////////////////////////////////////
  16. //
  17. //
  18. //
  19. template <class> struct storage_traits { };
  20. template <> struct storage_traits<CComPtr<IEnumWIA_DEV_INFO> > { typedef CIWiaPropertyStoragePtr storage_type; };
  21. template <> struct storage_traits<CComPtr<IEnumWIA_DEV_CAPS> > { typedef CWiaDevCap storage_type; };
  22. template <> struct storage_traits<CComPtr<IEnumWIA_FORMAT_INFO> > { typedef CWiaFormatInfo storage_type; };
  23. template <> struct storage_traits<CComPtr<IEnumWiaItem> > { typedef CIWiaItemPtr storage_type; };
  24. template <> struct storage_traits<CComPtr<CMyEnumSTATPROPSTG> > { typedef CStatPropStg storage_type; };
  25. //////////////////////////////////////////////////////////////////////////
  26. //
  27. //
  28. //
  29. template <class interface_type>
  30. void TestEnum(interface_type &pEnum, PCTSTR pInterfaceName)
  31. {
  32. m_pszContext = pInterfaceName;
  33. TestGetCount(pEnum);
  34. TestReset(pEnum);
  35. TestNext(pEnum);
  36. TestSkip(pEnum);
  37. TestClone(pEnum);
  38. m_pszContext = 0;
  39. }
  40. //////////////////////////////////////////////////////////////////////////
  41. //
  42. //
  43. //
  44. template <class interface_type>
  45. void TestNext(interface_type &pEnum)
  46. {
  47. typedef storage_traits<interface_type>::storage_type storage_type;
  48. ULONG nItems = -1;
  49. CHECK_HR(pEnum->GetCount(&nItems));
  50. if (nItems == 0)
  51. {
  52. return;
  53. }
  54. // try to get items; first, last, all, one more than all, past the last
  55. SubTestNext(pEnum, 0, 1, 1, S_OK);
  56. SubTestNext(pEnum, nItems-1, 1, 1, S_OK);
  57. SubTestNext(pEnum, 0, nItems, nItems, S_OK);
  58. SubTestNext(pEnum, 0, nItems+1, nItems, S_FALSE);
  59. SubTestNext(pEnum, nItems-1, 2, 1, S_FALSE);
  60. //SubTestNext(pEnum, nItems, 1, 0, S_FALSE);
  61. //SubTestNext(pEnum, 0, nItems, UINT_MAX, nItems);
  62. // try to pass 0 for celtFetched,
  63. // this should be allowed when fetching one item
  64. CHECK_HR(pEnum->Reset());
  65. CCppMem<storage_type> pOneItem(1);
  66. LOG_HR(pEnum->Next(1, &pOneItem[0], 0), == S_OK);
  67. if (m_bRunBadParamTests)
  68. {
  69. // try to pass 0 for celtFetched,
  70. // this should not be allowed when fetching more than one item
  71. CHECK_HR(pEnum->Reset());
  72. CCppMem<storage_type> pTwoItems(2);
  73. LOG_HR(pEnum->Next(2, &pTwoItems[0], 0), != S_OK);
  74. // try to pass 0 for the element array
  75. // this should not be allowed
  76. CHECK_HR(pEnum->Reset());
  77. ULONG nFetched = -1;
  78. LOG_HR(pEnum->Next(0, 0, &nFetched), != S_OK);
  79. }
  80. }
  81. //////////////////////////////////////////////////////////////////////////
  82. //
  83. //
  84. //
  85. template <class interface_type>
  86. void
  87. SubTestNext(
  88. interface_type &pEnum,
  89. ULONG nToBeSkipped,
  90. ULONG nAskedToBeFetched,
  91. ULONG nExpectedToBeFetched,
  92. HRESULT hrExpected
  93. )
  94. {
  95. typedef storage_traits<interface_type>::storage_type storage_type;
  96. CHECK_HR(pEnum->Reset());
  97. if (nToBeSkipped)
  98. {
  99. CHECK_HR(pEnum->Skip(nToBeSkipped));
  100. }
  101. CCppMem<storage_type> pItems(nAskedToBeFetched);
  102. ULONG nFetched = -1;
  103. HRESULT hrAPI = pEnum->Next(nAskedToBeFetched, &pItems[0], &nFetched);
  104. if (hrAPI != hrExpected)
  105. {
  106. LOG_ERROR(
  107. _T("pEnum->Next(%d, &pItems[0], &nFetched) == %s, expected %s"),
  108. nAskedToBeFetched,
  109. (PCTSTR) HResultToStr(hrAPI),
  110. (PCTSTR) HResultToStr(hrExpected)
  111. );
  112. }
  113. LOG_CMP(nFetched, ==, nExpectedToBeFetched);
  114. }
  115. //////////////////////////////////////////////////////////////////////////
  116. //
  117. //
  118. //
  119. template <class interface_type>
  120. void TestReset(interface_type &pEnum)
  121. {
  122. typedef storage_traits<interface_type>::storage_type storage_type;
  123. ULONG nItems = -1;
  124. CHECK_HR(pEnum->GetCount(&nItems));
  125. if (nItems == 0)
  126. {
  127. return;
  128. }
  129. // reset and read the first element
  130. CHECK_HR(pEnum->Reset());
  131. if (!m_bBVTMode)
  132. {
  133. storage_type FirstItemBeforeQueryingAll;
  134. CHECK_HR(pEnum->Next(1, &FirstItemBeforeQueryingAll, 0));
  135. // go to the last item
  136. HRESULT hr;
  137. do
  138. {
  139. storage_type Item;
  140. hr = pEnum->Next(1, &Item, 0);
  141. }
  142. while (hr == S_OK);
  143. // reset the enumerator and read the first element again
  144. CHECK_HR(pEnum->Reset());
  145. storage_type FirstItemAfterQueryingAll;
  146. CHECK_HR(pEnum->Next(1, &FirstItemAfterQueryingAll, 0));
  147. if (FirstItemBeforeQueryingAll != FirstItemAfterQueryingAll)
  148. {
  149. LOG_ERROR(_T("FirstItemBeforeQueryingAll != FirstItemAfterQueryingAll"));
  150. }
  151. }
  152. }
  153. //////////////////////////////////////////////////////////////////////////
  154. //
  155. //
  156. //
  157. template <class interface_type>
  158. void TestSkip(interface_type &pEnum)
  159. {
  160. typedef storage_traits<interface_type>::storage_type storage_type;
  161. // get the item count
  162. ULONG nItems = -1;
  163. CHECK_HR(pEnum->GetCount(&nItems));
  164. if (nItems == 0)
  165. {
  166. return;
  167. }
  168. // read and store each item
  169. CHECK_HR(pEnum->Reset());
  170. CCppMem<storage_type> pItems(nItems);
  171. for (int i = 0; i < nItems; ++i)
  172. {
  173. CHECK_HR(pEnum->Next(1, &pItems[i], 0));
  174. }
  175. // test valid cases
  176. for (int nToBeSkipped = 0; nToBeSkipped < nItems; ++nToBeSkipped)
  177. {
  178. CHECK_HR(pEnum->Reset());
  179. for (int nItem = nToBeSkipped; nItem < nItems; nItem += nToBeSkipped + 1)
  180. {
  181. CHECK_HR(pEnum->Skip(nToBeSkipped));
  182. storage_type Item;
  183. CHECK_HR(pEnum->Next(1, &Item, 0));
  184. if (Item != pItems[nItem])
  185. {
  186. LOG_ERROR(_T("Item != pItems[nItem] after skipping %d"), nToBeSkipped);
  187. }
  188. }
  189. }
  190. // test invalid cases
  191. if (m_bRunBadParamTests)
  192. {
  193. CHECK_HR(pEnum->Reset());
  194. LOG_HR(pEnum->Skip(nItems+1), == S_FALSE);
  195. CHECK_HR(pEnum->Reset());
  196. LOG_HR(pEnum->Skip(-1), == S_FALSE);
  197. }
  198. }
  199. //////////////////////////////////////////////////////////////////////////
  200. //
  201. //
  202. //
  203. template <class interface_type>
  204. void TestClone(interface_type &pEnum, bool bRecurse = true)
  205. {
  206. typedef storage_traits<interface_type>::storage_type storage_type;
  207. // make the clone
  208. interface_type pClone;
  209. if (LOG_HR(pEnum->Clone(&pClone), == S_OK) && !m_bBVTMode)
  210. {
  211. // reset both the original and the clone enumerators, then iterate
  212. // through each element one by one and compare them
  213. CHECK_HR(pEnum->Reset());
  214. CHECK_HR(pClone->Reset());
  215. HRESULT hr, hr1, hr2;
  216. while (1)
  217. {
  218. // also, make a clone of the current state and check that
  219. // the state is captured in the clone
  220. interface_type pClone2;
  221. CHECK_HR(pEnum->Clone(&pClone2));
  222. // get the next item from the original interface
  223. storage_type Item;
  224. hr = pEnum->Next(1, &Item, 0);
  225. // get the next item from the first clone
  226. storage_type Item1;
  227. hr1 = pClone->Next(1, &Item1, 0);
  228. // get the next item from the second clone
  229. storage_type Item2;
  230. hr2 = pClone2->Next(1, &Item2, 0);
  231. if (hr != S_OK || hr1 != S_OK || hr2 != S_OK)
  232. {
  233. break;
  234. }
  235. if (Item != Item1 || Item1 != Item2)
  236. {
  237. LOG_ERROR(_T("Clone states are not equal"));
  238. }
  239. }
  240. if (hr != S_FALSE || hr1 != S_FALSE || hr2 != S_FALSE)
  241. {
  242. LOG_ERROR(_T("After enumeration, clone states are not equal"));
  243. }
  244. // test the clone
  245. TestNext(pClone);
  246. TestReset(pClone);
  247. TestSkip(pClone);
  248. if (bRecurse)
  249. {
  250. TestClone(pClone, false);
  251. }
  252. TestGetCount(pClone);
  253. }
  254. // test bad param
  255. if (m_bRunBadParamTests)
  256. {
  257. LOG_HR(pEnum->Clone(0), != S_OK);
  258. }
  259. }
  260. //////////////////////////////////////////////////////////////////////////
  261. //
  262. //
  263. //
  264. template <class interface_type>
  265. void TestGetCount(interface_type &pEnum)
  266. {
  267. typedef storage_traits<interface_type>::storage_type storage_type;
  268. // First, get the item count using GetCount()
  269. ULONG cItemsFromGetCount = 0;
  270. if (LOG_HR(pEnum->GetCount(&cItemsFromGetCount), == S_OK) && !m_bBVTMode)
  271. {
  272. // Now, find the item count by first resetting the enumerator
  273. // and then querying for each item one by one using Next()
  274. ULONG cItemsFromNext = 0;
  275. CHECK_HR(pEnum->Reset());
  276. HRESULT hr;
  277. do
  278. {
  279. // verify that GetCount returns the same result after a Next or Reset
  280. ULONG cItemsFromGetCountNow = 0;
  281. LOG_HR(pEnum->GetCount(&cItemsFromGetCountNow), == S_OK);
  282. LOG_CMP(cItemsFromGetCountNow, ==, cItemsFromGetCount);
  283. // get the next item
  284. storage_type Item;
  285. ULONG cFetched = 0;
  286. hr = pEnum->Next(1, &Item, &cFetched);
  287. cItemsFromNext += cFetched;
  288. }
  289. while (hr == S_OK);
  290. LOG_HR(hr, == S_FALSE);
  291. // verify that the two counts are equal
  292. LOG_CMP(cItemsFromNext, ==, cItemsFromGetCount);
  293. }
  294. // test bad param
  295. if (m_bRunBadParamTests)
  296. {
  297. LOG_HR(pEnum->GetCount(0), != S_OK);
  298. }
  299. }
  300. #endif //DEFINE_TEMPLATES