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.
 
 
 
 
 
 

244 lines
6.9 KiB

/* Test driver for class HashTable */
/* Author: Paul Larson, [email protected] */
/* Much hacked upon by George V. Reilly, [email protected] */
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "str-num.h"
#ifdef LKR_APPLY_IF
// A class to exercise ApplyIf()
class CApplyIfTest
{
public:
static LK_PREDICATE WINAPI
Predicate(const CTest* pTest, void* pvState)
{
CApplyIfTest* pThis = static_cast<CApplyIfTest*>(pvState);
++pThis->m_cPreds;
IRTLTRACE("CApplyIfTest::Predicate(%p (%s, %d), %p)\n",
pTest, pTest->m_sz, pTest->m_n, pThis);
return ((pTest->m_n % 10 == 7)
? LKP_PERFORM
: LKP_NO_ACTION);
}
static LK_ACTION WINAPI
Action(const CTest* pTest, void* pvState)
{
CApplyIfTest* pThis = static_cast<CApplyIfTest*>(pvState);
++pThis->m_cActions;
LK_ACTION lka = ((pTest->m_n > 30)
? LKA_SUCCEEDED
: LKA_FAILED);
IRTLTRACE("CApplyIfTest::Action(%p (%s, %d), %p) %s\n",
pTest, pTest->m_sz, pTest->m_n, pThis,
lka == LKA_SUCCEEDED ? "succeeded" : "failed");
if (lka == LKA_SUCCEEDED)
++pThis->m_cSuccesses;
else if (lka == LKA_FAILED)
++pThis->m_cFailures;
return lka;
}
int m_cPreds;
int m_cActions;
int m_cSuccesses;
int m_cFailures;
CApplyIfTest()
: m_cPreds(0), m_cActions(0), m_cSuccesses(0), m_cFailures(0)
{}
};
// The Predicate and Action functions can be static member functions,
// but don't have to be
LK_PREDICATE WINAPI
DeleteIfGt10(
const CTest* pTest,
void* pvState)
{
IRTLTRACE("DeleteIfGt10(%p, %s, %p) = %d\n",
pTest, pTest->m_sz, pvState, pTest->m_n);
return ((pTest->m_n > 10)
? LKP_PERFORM
: LKP_NO_ACTION);
}
#endif // LKR_APPLY_IF
void Test(
bool fVerbose)
{
// Some objects for the hash tables
CTest tl(5, "Larson", true);
CTest tk(17, "Krishnan", false);
CTest tr(37, "Reilly", true);
// A string-keyed hash table
CStringTestHashTable stht;
IRTLVERIFY(LK_SUCCESS == stht.InsertRecord(&tl));
IRTLVERIFY(LK_SUCCESS == stht.InsertRecord(&tk));
IRTLVERIFY(LK_SUCCESS == stht.InsertRecord(&tr));
IRTLTRACE("Check the overwrite feature of InsertRecord\n");
IRTLVERIFY(LK_KEY_EXISTS == stht.InsertRecord(&tr, false));
IRTLASSERT(tr.m_cRefs == 1);
IRTLVERIFY(LK_SUCCESS == stht.InsertRecord(&tr, true));
IRTLASSERT(tr.m_cRefs == 1); // 1+1-1 == 1
IRTLTRACE("Check that the keys are really present in the table and that "
"the refcounting works\n");
const CTest* pTest = NULL;
IRTLVERIFY(LK_SUCCESS == stht.FindKey(tl.m_sz, &pTest) && pTest == &tl);
IRTLASSERT(tl.m_cRefs == 2);
IRTLVERIFY(LK_SUCCESS == stht.FindKey(tk.m_sz, &pTest) && pTest == &tk);
IRTLASSERT(tk.m_cRefs == 2);
IRTLVERIFY(LK_SUCCESS == stht.FindKey(tr.m_sz, &pTest) && pTest == &tr);
IRTLASSERT(tr.m_cRefs == 2);
IRTLVERIFY(LK_SUCCESS == stht.FindRecord(&tr));
IRTLASSERT(tr.m_cRefs == 2); // FindRecord does not addref
IRTLTRACE("Look for a key under an alternate spelling "
"(case-insensitive)\n");
IRTLVERIFY(LK_SUCCESS == stht.FindKey("rEiLlY", &pTest) && pTest == &tr);
IRTLASSERT(tr.m_cRefs == 3);
IRTLTRACE("Release the references added by FindKey\n");
stht.AddRefRecord(&tl, LKAR_EXPLICIT_RELEASE);
tk.m_cRefs--;
tr.m_cRefs = 1;
IRTLTRACE("Now build the numeric hash table\n");
CNumberTestHashTable ntht;
IRTLVERIFY(LK_SUCCESS == ntht.InsertRecord(&tl));
IRTLVERIFY(LK_SUCCESS == ntht.InsertRecord(&tk));
IRTLVERIFY(LK_SUCCESS == ntht.InsertRecord(&tr));
#ifdef LKR_APPLY_IF
IRTLTRACE("Test ApplyIf()\n");
CApplyIfTest ait;
IRTLVERIFY(1 == ntht.ApplyIf(ait.Predicate, ait.Action, &ait));
IRTLASSERT(3 == ait.m_cPreds && 2 == ait.m_cActions
&& 1 == ait.m_cSuccesses && 1 == ait.m_cFailures);
IRTLTRACE("Test DeleteIf()\n");
IRTLASSERT(3 == ntht.Size());
ntht.DeleteIf(DeleteIfGt10, NULL);
IRTLASSERT(1 == ntht.Size());
IRTLTRACE("Check that the keys that were supposed to be deleted "
"really are gone\n");
IRTLASSERT(tl.m_n <= 10);
IRTLVERIFY(LK_SUCCESS == ntht.FindKey(tl.m_n, &pTest) && pTest == &tl);
ntht.AddRefRecord(pTest, LKAR_EXPLICIT_RELEASE); // release ref
IRTLASSERT(tk.m_n > 10);
IRTLVERIFY(LK_NO_SUCH_KEY == ntht.FindKey(tk.m_n, &pTest)
&& pTest == NULL);
IRTLASSERT(tr.m_n > 10);
IRTLVERIFY(LK_NO_SUCH_KEY == ntht.FindKey(tr.m_n, &pTest)
&& pTest == NULL);
IRTLVERIFY(LK_SUCCESS == ntht.DeleteKey(tl.m_n));
IRTLASSERT(0 == ntht.Size());
#endif // LKR_APPLY_IF
#ifdef LKR_DEPRECATED_ITERATORS
IRTLTRACE("Check Iterators\n");
DWORD cRec = 0;
CStringTestHashTable::CIterator iter;
LK_RETCODE lkrc = stht.InitializeIterator(&iter);
while (lkrc == LK_SUCCESS)
{
++cRec;
CStringTestHashTable::Key pszKey = iter.Key();
CStringTestHashTable::Record* pRec = iter.Record();
IRTLASSERT(pRec == &tl || pRec == &tk || pRec == &tr);
if (fVerbose)
printf("Record(%p) contains \"%s\"\n", pRec, pszKey);
lkrc = stht.IncrementIterator(&iter);
}
IRTLASSERT(lkrc == LK_NO_MORE_ELEMENTS);
lkrc = stht.CloseIterator(&iter);
IRTLASSERT(lkrc == LK_SUCCESS);
IRTLASSERT(cRec == stht.Size());
IRTLTRACE("Check const iterators\n");
const CStringTestHashTable& sthtConst = stht;
CStringTestHashTable::CConstIterator iterConst;
cRec = 0;
lkrc = sthtConst.InitializeIterator(&iterConst);
while (lkrc == LK_SUCCESS)
{
++cRec;
const CStringTestHashTable::Key pszKey = iterConst.Key();
const CStringTestHashTable::Record* pRec = iterConst.Record();
IRTLASSERT(pRec == &tl || pRec == &tk || pRec == &tr);
if (fVerbose)
printf("Const Record(%p) contains \"%s\"\n", pRec, pszKey);
lkrc = sthtConst.IncrementIterator(&iterConst);
}
IRTLASSERT(lkrc == LK_NO_MORE_ELEMENTS);
lkrc = sthtConst.CloseIterator(&iterConst);
IRTLASSERT(lkrc == LK_SUCCESS);
IRTLASSERT(cRec == sthtConst.Size());
#endif // LKR_DEPRECATED_ITERATORS
#if 0
IRTLTRACE("Check Clear\n");
stht.Clear();
IRTLASSERT(0 == stht.Size());
#else
IRTLTRACE("Check DeleteKey\n");
IRTLVERIFY(LK_SUCCESS == stht.DeleteKey(tl.m_sz));
IRTLVERIFY(LK_SUCCESS == stht.DeleteKey(tk.m_sz));
IRTLVERIFY(LK_SUCCESS == stht.DeleteKey(tr.m_sz));
#endif
IRTLTRACE("Test done\n");
// ~CTest will check for m_cRefs==0
}
int __cdecl
main(
int argc,
char **argv)
{
Test(true);
return(0) ;
} /* main */