home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
-
- Test out the Tree, List, Stack, and Queue Routines in MEMLIB.LIB
-
-
- ****************************************************************************/
-
- #include <stdio.h>
-
- #if C_UNIX
- #include <signal.h>
- #endif
-
-
- #include <memlib.h>
-
- #ifdef C_ANSI
- #include <string.h>
- #include <stdlib.h>
- #include <conio.h>
- #endif
-
-
- #define MAX_STR_LEN 20 /* maximum length of any string */
-
- #define TEST_MEMBERS (250) /* number of test elements/cases */
- #define TEST_MAX_RUNS 1600
-
-
- #define M_LIST 1 /* Link list */
- #define M_TREE 2 /* Binary tree */
- #define M_STACK 3 /* stack (LIFO) */
- #define M_QUEUE 4 /* queue (FIFO) */
- #define M_HEAP 5 /* heap (priority queue) */
- #define M_VMM 6 /* virtual memory */
- #define M_TEST_ALL 7
-
- /*
- ** The TEST_S structure is used as an independant data store to verify
- ** the accuracy of the data store being tested. It is the 'control'
- ** for these experiments
- */
-
- struct TEST_S{
- CHAR szName[MAX_STR_LEN]; /* alpha form of id = number */
- SHORT sId; /* numeric of id */
- SHORT sMode; /* sMode, TRUE = in data store,
- FALSE = not in data store */
- };
-
- typedef struct TEST_S TEST_T;
- typedef TEST_T * TEST_P;
- typedef TEST_T ** TEST_PP;
-
-
- #define NAME_SIZE 3+1
-
-
-
-
- /*
- ** (ANSI) Prototypes for local functions
- */
-
- #ifdef C_ANSI
- SHORT
- CompareData(PVOID pvData1,PVOID pvData2);
- #else
- SHORT
- CompareData();
- #endif
-
-
-
- #if C_UNIX
-
- void set_signal();
- void KILL();
-
- #endif
-
-
- int fKILL = 0; /* set if UNIX stop */;
-
-
- /*
- ** Init Menu Selections for user
- */
-
- CHAR szTestName[M_TEST_ALL][40] = { "Link List",
- "Binary Tree",
- "Stack",
- "Queue",
- "Heap",
- "Virtual Memory",
- "All" };
-
- #define BACK_SPACE 8
- #define SPIN_SIZE 8
-
- CHAR cSpin[SPIN_SIZE];
-
-
- LONG lHandle[TEST_MEMBERS];
-
-
- int main()
- {
-
- TNODE_P psTreeRoot = NULL; /* tree root member, initialize to NULL */
- TNODE_P psWorkNode; /* working/scratch nodes */
-
- LLIST_P psListHead = NULL; /* head used for list, stack, queue */
- LLIST_P psListTail = NULL; /* tail used for queue */
- LLIST_P psWorkMember; /* working member */
-
- HEAP_P psHeap; /* heap control structure */
- HEAP_DATA_P psHeapData; /* heap data structure */
-
- SHORT sPriority; /* priority for heap */
-
- PVOID pvData; /* work variable */
-
- TEST_P pstTest; /* working test type */
-
-
- SHORT sSel; /* current test case */
-
- LONG lTestErrors[M_TEST_ALL-1]; /* counter for errors if any occur */
-
- int sSelection; /* menu selection, test types */
- BOOL fInData; /* if test in data structures */
- int iCnt;
- ULONG ulTestIterations[M_TEST_ALL-1];
- ULONG ulMasterIterations[M_TEST_ALL-1];
-
- SHORT sTestMode;
-
- static TEST_T stTest[TEST_MEMBERS + 1]; /* test cases */
-
- SHORT sSpinner = 0;
-
- CHAR * pcData;
-
-
- #if C_UNIX
- set_signal();
- #endif
-
-
-
- for(sSelection = 0; sSelection < (M_TEST_ALL -1); sSelection++)
- {
- lTestErrors[sSelection] = 0;
- ulTestIterations[sSelection] = 0;
- ulMasterIterations[sSelection] = 0;
- }
-
-
- cSpin[0] = '|';
- cSpin[1] = '/';
- cSpin[2] = '-';
- cSpin[3] = '\\';
- cSpin[4] = cSpin[0];
- cSpin[5] = cSpin[1];
- cSpin[6] = cSpin[2];
- cSpin[7] = cSpin[3];
-
- printf("\n\n");
- printf("MEM C Algorithms v 2.0 - Test program\n\n");
- printf("1 Link List\n");
- printf("2 Binary Tree\n");
- printf("3 Stack\n");
- printf("4 Queue\n");
- printf("5 Heap\n");
- printf("6 Virtual Memory\n");
- printf("7 Test All\n\n");
-
- scanf("%d",&sSelection);
-
-
- /*
- ** Make sure selection in range, else exit
- */
-
- if(
- (sSelection >= M_LIST) &&
- (sSelection <= M_TEST_ALL)
- )
- {
- ;
- }
- else
- exit(1);
-
-
- sTestMode = sSelection; /* remember */
-
-
- /*
- ** Load up the test control data
- */
-
- for(sSel = 1; sSel < TEST_MEMBERS; sSel++)
- {
- sprintf(stTest[sSel].szName,"%d",sSel);
- stTest[sSel].sId = sSel;
- stTest[sSel].sMode = C_FALSE;
- }
-
-
- /*
- ** Heap is only data type requiring initialization beyond just
- ** setting pointer to NULL. The heap is implemented in an array
- ** so the array must be alloc'd before use.
- */
-
- if(sSelection >= M_HEAP)
- MemHepInit(&psHeap, TEST_MEMBERS);
-
- if(sSelection >= M_VMM)
- {
- VmmInit(64,"swap.dat");
- for(iCnt = 0; iCnt < TEST_MEMBERS; iCnt++)
- lHandle[iCnt] = -1;
- }
-
- if(sSelection > (M_TEST_ALL -1))
- sSelection = M_LIST;
-
-
-
- printf("Errors will be printed if they occur......");
-
- #ifdef C_ANSI
- printf("\nHit any key to end test\n");
- #else
- printf("\nHit Ctrl-C to end test\n");
- #endif
-
-
- printf("\nTesting %s ", szTestName[sSelection - 1]);
-
- while(!fKILL)
- {
-
- /*
- ** Select test member at random
- */
-
- sSel = rand() % TEST_MEMBERS;
-
- #ifdef DEBUG
- #else
- SpinCheck(&sSpinner);
- #endif
-
- #ifdef DEBUG
- printf("%d",sSel);
- #endif
-
- /*
- ** Process if control says should not be in data store
- */
-
-
- /*
- ** Check everything
- */
-
- for(iCnt = 0; iCnt < TEST_MEMBERS; iCnt++)
- {
- switch(sSelection)
- {
- case M_LIST:
- case M_STACK:
- case M_QUEUE:
-
- MemLstFindMember(psListHead,(PCHAR) stTest[iCnt].szName,CompareData,&psWorkMember);
- fInData = (psWorkMember != NULL);
- break;
-
- case M_TREE:
-
- MemTreFindNode(psTreeRoot,(PVOID) stTest[iCnt].szName,CompareData,&psWorkNode);
-
- fInData = (psWorkNode != NULL);
- break;
-
- case M_HEAP:
-
- MemHepSearch(psHeap,(PVOID) stTest[iCnt].szName,CompareData,&psHeapData);
- fInData = (psHeapData != NULL);
- break;
-
- case M_VMM:
- if(lHandle[iCnt] != -1)
- {
- VmmPrep(lHandle[iCnt],&pcData);
- if(strcmp(pcData, stTest[iCnt].szName) == 0)
- fInData = 1;
- else
- fInData = 0;
- }
- else
- fInData = 0;
-
- }
-
-
- if(fInData != stTest[iCnt].sMode)
- {
- if(stTest[iCnt].sMode)
- printf("\nDid not find %d - should have been in %s\n", iCnt, szTestName[sSelection - 1]);
- else
- printf("\nFound %d - should not have been in %s\n", iCnt, szTestName[sSelection - 1]);
-
- lTestErrors[sSelection -1]++;
- printf("Total errors = %d\n",lTestErrors[sSelection - 1]);
- }
- }
-
-
-
-
-
- if(stTest[sSel].sMode == C_FALSE)
- {
- #ifdef DEBUG
- printf("+");
- #endif
- /*
- ** Add to data store
- */
-
- switch(sSelection)
- {
- case M_LIST:
-
- MemLstAllocMember(&psWorkMember);
- if(psWorkMember != NULL)
- {
- psWorkMember -> pvData = (PVOID) &stTest[sSel];
- }
- else
- printf("\nno member allocated\n");
-
- MemLstInsertMember(psListHead,psWorkMember,CompareData,&psListHead);
- break;
-
- case M_STACK:
-
- MemStkPush(&psListHead, (PVOID) &stTest[sSel]);
- break;
-
- case M_QUEUE:
-
- MemQueEnqMember(&psListHead, &psListTail, (PVOID) &stTest[sSel]);
- break;
-
- case M_TREE:
-
- MemTreAllocNode(&psWorkNode);
- if(psWorkNode != NULL)
- {
- psWorkNode -> pvData = (PVOID) &stTest[sSel];
- }
- else
- printf("\nno member allocated\n");
-
- MemTreInsertNode(psTreeRoot,psWorkNode,CompareData,&psTreeRoot);
- /* printf("I=%d, ",sSel); */
-
- break;
-
- case M_HEAP:
-
- MemHepEnque(psHeap,sSel,(PVOID) &stTest[sSel]);
- break;
-
- case M_VMM:
-
- VmmAlloc(1,NAME_SIZE, &lHandle[sSel]);
- VmmPrep(lHandle[sSel],&pcData);
- memcpy(pcData,stTest[sSel].szName,NAME_SIZE);
- break;
-
- }
-
- /*
- ** Mark control as being in data store
- */
-
- stTest[sSel].sMode = C_TRUE;
-
- }
- else if(stTest[sSel].sMode == C_TRUE)
- {
-
- /*
- ** Process if control says should be in data store
- */
-
- #ifdef DEBUG
- printf("-");
- #endif
- /*
- ** Remove from data store
- */
-
- /*
- ** Usage of Stacks, Queues, and Heaps requires that
- ** the member removed is not selectable.
- **
- ** For stacks, it is the item on top.
- ** For queues, it is the oldest item.
- ** For heaps, it is the item with the highest priority
- **
- ** Because of this, stack, queue, and heap item removals
- ** also reset the control number (sSel) to that of the
- ** item which was removed
- */
-
-
- switch(sSelection)
- {
- case M_LIST:
-
- MemLstFindMember(psListHead,(PCHAR) stTest[sSel].szName,CompareData,&psWorkMember);
- MemLstDeleteMember(psListHead,psWorkMember,&psListHead);
-
- break;
-
- case M_STACK:
-
- MemStkPop(&psListHead, &pvData);
- pstTest = (TEST_P) pvData;
- sSel = pstTest -> sId;
-
- break;
-
- case M_QUEUE:
-
- MemQueDeqMember(&psListHead, &psListTail, &pvData);
- pstTest = (TEST_P) pvData;
- sSel = pstTest -> sId;
-
- break;
-
- case M_TREE:
-
- MemTreDeleteNode(psTreeRoot,(PVOID) stTest[sSel].szName,CompareData,&psTreeRoot);
-
- break;
-
- case M_HEAP:
-
- MemHepDeque(psHeap,&sPriority,&pvData);
- pstTest = (TEST_P) pvData;
- sSel = pstTest -> sId;
- break;
-
- case M_VMM:
-
- VmmPrep(lHandle[sSel],&pcData);
- VmmFree(lHandle[sSel]);
- lHandle[sSel] = -1;
- break;
-
- }
- #ifdef DEBUG
- printf("D ",sSel);
- #endif
- stTest[sSel].sMode = C_FALSE;
-
- }
-
- /*
- ** You will note that this program uses 'goto'. After years of
- ** heartburn with goto's, there has developed in the programming
- ** community a phobia of using goto at all. Even the SLC shows this.
- ** There have even been languages created which do not have a goto
- ** (Modula-2). I feel there is a case for using goto only under
- ** 1 condition, there is only one label to 'goto' and the goto
- ** is always towards the bottom of the function or to exit
- ** the function.
- **
- ** Without using any goto's, you end up with extra levels of 'if'
- ** statements and code that is harder to read and has higher
- ** essential and cyclomatic complexities (cf. Software Metrics, McCabe).
- **
- ** If you are in a module and have encountered a condition that means
- ** there is nothing else you can do there, GET OUT!. Don't keep
- ** setting return codes and checking return codes as you fall-through
- ** the module, just get out. There should be only one entry point and
- ** exit point from the module so you should NOT have multiple return
- ** statements. You should goto the common exit label and return
- ** from there. The goto itself should normally be masked with a
- ** define (cf C_LEAVE() in MEMDEF.H).
- **
- */
-
- LOOP_BOT:
-
- ulTestIterations[sSelection - 1]++;
- ulMasterIterations[sSelection - 1]++;
-
-
- if(sTestMode == M_TEST_ALL)
- {
- if(ulTestIterations[sSelection - 1] >= TEST_MAX_RUNS)
- {
- sSpinner = 0;
-
- switch(sSelection)
- {
-
- #ifdef DEBUG
- printf("\nVACATE\n");
- #endif
-
- case M_LIST:
-
- case M_QUEUE:
-
- MemLstVacateList(&psListHead, C_FALSE);
- break;
-
- case M_TREE:
-
- MemTreVacateTree(&psTreeRoot, C_FALSE);
- break;
-
- case M_STACK:
-
- MemStkVacateStack(&psListHead, C_FALSE);
- break;
-
- case M_HEAP:
-
- MemHepVacateHeap(&psHeap, C_FALSE);
- MemHepInit(&psHeap, TEST_MEMBERS);
- break;
-
- case M_VMM:
- break;
- }
-
- ulTestIterations[sSelection - 1] = 0;
-
- for(sSel = 0; sSel < TEST_MEMBERS; sSel++)
- {
- stTest[sSel].sMode = C_FALSE;
- }
-
- sSelection++;
- if(sSelection > (M_TEST_ALL-1))
- sSelection = M_LIST;
-
- printf("\nTesting %s ", szTestName[sSelection - 1]);
- }
- }
-
-
- #ifdef C_ANSI
- if(kbhit())
- fKILL = 1;
- #endif
-
- }
-
- /* getch(); */ /* get the character at the keyboard */
-
- if(sTestMode >= M_HEAP)
- MemHepVacateHeap(&psHeap,C_FALSE);
-
- if(sTestMode >= M_VMM)
- VmmTerm();
-
- printf("\n");
-
- if(sTestMode <= (M_TEST_ALL -1))
- {
- printf("\n%s Test ", szTestName[sSelection-1]);
- printf(" = %u iterations ", ulMasterIterations[sSelection-1]);
- printf("with %d errors.\n",lTestErrors[sSelection-1]);
- }
- else
- {
- for(sSelection = 0; sSelection < (M_TEST_ALL-1); sSelection++)
- {
- printf("\n%s Test ", szTestName[sSelection]);
- printf(" = %u iterations ", ulMasterIterations[sSelection]);
- printf("with %d errors.\n",lTestErrors[sSelection]);
- }
- }
-
- }
-
-
-
- #ifdef C_ANSI
- SHORT
- CompareData(PVOID pvData1,PVOID pvData2)
- #else
- SHORT
- CompareData(pvData1,pvData2)
- PVOID pvData1;
- PVOID pvData2;
- #endif
- {
- return(strcmp((PCHAR) pvData1,(PCHAR) pvData2));
- }
-
-
- #if C_UNIX
-
- void set_signal()
- {
- signal(SIGHUP, KILL);
- signal(SIGINT, KILL); /* this one works for cntl c */
- signal(SIGQUIT, KILL);
- signal(SIGILL, KILL);
- signal(SIGTRAP, KILL);
- signal(SIGABRT, KILL);
- signal(SIGEMT, KILL);
- signal(SIGFPE, KILL);
- signal(SIGKILL, KILL);
- signal(SIGBUS, KILL);
- signal(SIGSYS, KILL);
- signal(SIGPIPE, KILL);
- signal(SIGALRM, KILL);
- signal(SIGTERM, KILL);
- }
-
- void KILL()
- {
- fKILL = 1;
- }
-
-
- #endif
-
-
-
-
- int
- SpinCheck(psSpinner)
- PSHORT psSpinner;
- {
- static SHORT sCnt = 0;
-
- (*psSpinner)++;
-
- if((*psSpinner) > (SPIN_SIZE * 100))
- *psSpinner = 0;
-
- if((*psSpinner) % 50)
- {
- sCnt++;
- if(sCnt >= SPIN_SIZE)
- sCnt = 0;
-
- printf("%c",BACK_SPACE);
- printf("%c",cSpin[sCnt]);
-
- #if C_UNIX
- fflush(stdout);
- #endif
-
- }
- }
-
-
-