/*************************** driver.c ************************************** Purpose: Test driver program for boolean operations code. Provenance: Written and tested by S. Wartik, April 1991. Notes: This module contains a main program and accompanying subroutines that, when compiled, exercise every function of the boolean operations module. The testing is purely in terms of the external interface that the boolean operations module presents. That is, the effects of constructor functions are examined through the projector functions. This makes the code (almost) implementation- independent. For this reason, it may be used (with slight modifications, controlled through #ifdef's) to test both the bit-vector and the hashing implementations. Usage for the bit-vector version is: driver lower-bound upper-bound where the bounds specify the legal domain of the set. In the current implementation, abs(upper-bound - lower-bound) must be less than 256. **/ #include # include "bv.h" #define N_SETS 3 #define MIN_ELEMENTS 5 /* Make the tests "interesting". */ /* Require at least 5 elements. */ void Exit_If_Error_On(); void Exit_Indicating_Failed_Op(); void Test_Set_Operators(); /* The main routine is implemented */ void Test_Union_Operators(); /* as a series of calls to several */ void Test_Intersection_Operators(); /* procedures, each of which tests */ void Test_Subtraction_Operators(); /* a particular aspect of the */ void Test_Copy(); /* module. */ void Test_Iterate(); boolean Iterator(); main(argc, argv) int argc; char *argv[]; { set s[N_SETS]; int lower, upper; int i; if ( argc != 3 ) { printf("Usage: %s lower-bound upper-bound\n", argv[0]); exit(1); } lower = atoi(argv[1]); upper = atoi(argv[2]); if ( upper < lower+MIN_ELEMENTS ) { printf("Please specify a set that can contain at least %d elements.\n", MIN_ELEMENTS); exit(1); } else if ( upper - lower > MAX_ELEMENTS-1 ) { printf("This implementation can't accommodate upper-lower>%d.\n", MAX_ELEMENTS-1); exit(1); } for ( i = 0; i < N_SETS; i++ ) { /* Test creation. */ Create(lower, upper, &s[i]); Exit_If_Error_On("Create"); } fputs("Creation works.\n", stdout); for ( i = 0; i < 2; i++ ) { /* Test clearing sets. */ Clear(&s[i]); Exit_If_Error_On("Clear"); if ( Empty(&s[i]) ) Exit_If_Error_On("Empty"); else Exit_Indicating_Failed_Op("Empty"); } fputs("Clearing works.\n", stdout); Test_Set_Operators(s, lower, upper); fputs("Basic operators works.\n", stdout); Test_Union_Operators(s, lower, upper); fputs("Union works.\n", stdout); Test_Intersection_Operators(s, lower, upper); fputs("Intersection works.\n", stdout); Test_Subtraction_Operators(s, lower, upper); fputs("Subtraction works.\n", stdout); Test_Copy(s, lower, upper); fputs("Copying works.\n", stdout); Test_Iterate(s, lower, upper); fputs("Iterating works.\n", stdout); fputs("\nThe implementation passes.\n", stdout); exit(0); } void Test_Set_Operators(s, lower, upper) set s[]; int lower, upper; { int i; for ( i = lower; i <= upper; i++ ) { /* Test insertion of all */ Insert(&s[0], i); /* valid elements for a */ Exit_If_Error_On("Insert"); /* set that doesn't already */ if ( Member(&s[0], i) ) /* contain them. */ Exit_If_Error_On("Member"); else Exit_Indicating_Failed_Op("Member"); } for ( i = lower; i <= upper; i++ ) { /* Test insertion of all */ Insert(&s[0], i); /* valid elements for a */ Exit_If_Error_On("Insert"); /* set that already has */ if ( Member(&s[0], i) ) /* them. */ Exit_If_Error_On("Member"); else Exit_Indicating_Failed_Op("Member"); } for ( i = lower; i <= upper; i++ ) { /* Test deletion of all */ Delete(&s[0], i); /* valid elements when */ Exit_If_Error_On("Delete"); /* the set already has */ if ( ! Member(&s[0], i) ) /* them. */ Exit_If_Error_On("Delete"); else Exit_Indicating_Failed_Op("Member"); } for ( i = lower; i <= upper; i++ ) { /* Test deletion of all */ Delete(&s[0], i); /* valid elements when */ Exit_If_Error_On("Delete"); /* the set doesn't have */ if ( ! Member(&s[0], i) ) /* them. */ Exit_If_Error_On("Delete"); else Exit_Indicating_Failed_Op("Member"); } } void Test_Union_Operators(s, lower, upper) set s[]; int lower, upper; { int i; Insert(&s[0], lower); /* Test union of a set */ Exit_If_Error_On("Insert"); /* with an empty set. */ Unite(&s[0], &s[1], &s[2]); /* s2 <- {lower}U{} */ Exit_If_Error_On("Unite"); if ( Member(&s[2], lower) ) Exit_If_Error_On("Member"); else Exit_Indicating_Failed_Op("Member|Unite"); for ( i = lower+1; i <= upper; i++ ) if ( Member(&s[2], i) ) Exit_Indicating_Failed_Op("Member|Unite"); else Exit_If_Error_On("Member"); Insert(&s[1], lower+1); /* Test union of two non- */ Exit_If_Error_On("Insert"); /* empty, non-intersecting */ Unite(&s[0], &s[1], &s[2]); /* sets. */ Exit_If_Error_On("Unite"); /* s2 <- {lower}U{lower+1} */ if ( Member(&s[2], lower) && Member(&s[2], lower+1) ) Exit_If_Error_On("Member"); else Exit_Indicating_Failed_Op("Member|Unite"); for ( i = lower+2; i <= upper; i++ ) if ( Member(&s[2], i) ) Exit_Indicating_Failed_Op("Member|Unite"); else Exit_If_Error_On("Member"); /* Test union of two non-empty, */ Insert(&s[0], lower+1); /* intersecting sets. */ Exit_If_Error_On("Insert"); /* s2 <- {lower,lower+1} U */ Unite(&s[0], &s[1], &s[2]); /* {lower+1} */ Exit_If_Error_On("Unite"); if ( Member(&s[2], lower) && Member(&s[2], lower+1) ) Exit_If_Error_On("Member"); else Exit_Indicating_Failed_Op("Member|Unite"); for ( i = lower+2; i <= upper; i++ ) if ( Member(&s[2], i) ) Exit_Indicating_Failed_Op("Member|Unite"); else Exit_If_Error_On("Member"); } void Test_Intersection_Operators(s, lower, upper) set s[]; int lower, upper; { int i; Clear(&s[0]); Clear(&s[1]); Insert(&s[0], lower); /* Test intersection of a */ Exit_If_Error_On("Insert"); /* set with an empty set. */ Intersect(&s[0], &s[1], &s[2]); /* s2 <- {lower}^{} */ Exit_If_Error_On("Intersect"); for ( i = lower; i <= upper; i++ ) if ( Member(&s[2], i) ) Exit_Indicating_Failed_Op("Member|Intersect"); else Exit_If_Error_On("Member"); Insert(&s[0], lower); /* Test intersection of two */ Exit_If_Error_On("Insert"); /* non-empty, non-intersecting */ Insert(&s[1], lower+1); /* sets. */ Exit_If_Error_On("Insert"); /* s2 <- {lower}^{lower+1} */ Intersect(&s[0], &s[1], &s[2]); Exit_If_Error_On("Intersect"); for ( i = lower; i <= upper; i++ ) if ( Member(&s[2], i) ) Exit_Indicating_Failed_Op("Member|Intersect"); else Exit_If_Error_On("Member"); Insert(&s[0], lower); /* Test intersection of two non- */ Exit_If_Error_On("Insert"); /* non-empty, intersecting sets. */ Insert(&s[0], lower+1); /* s2 <- {lower,lower+1}^ */ Exit_If_Error_On("Insert"); /* {lower,lower+2} */ Clear(&s[1]); Insert(&s[1], lower); Exit_If_Error_On("Insert"); Insert(&s[1], lower+2); Exit_If_Error_On("Insert"); Intersect(&s[0], &s[1], &s[2]); Exit_If_Error_On("Intersect"); if ( Member(&s[2], lower) ) Exit_If_Error_On("Member"); else Exit_Indicating_Failed_Op("Member|Intersect"); for ( i = lower+1; i <= upper; i++ ) if ( Member(&s[2], i) ) Exit_Indicating_Failed_Op("Member|Intersect"); else Exit_If_Error_On("Member"); } void Test_Subtraction_Operators(s, lower, upper) set s[]; int lower, upper; { int i; Clear(&s[0]); /* Subtract one empty set */ Clear(&s[1]); /* from another. */ Subtract(&s[0], &s[1], &s[2]); Exit_If_Error_On("Subtract"); for ( i = lower; i <= upper; i++ ) if ( Member(&s[2], i) ) Exit_Indicating_Failed_Op("Member|Subtract"); else Exit_If_Error_On("Member"); } void Test_Copy(s, lower, upper) set s[]; int lower, upper; { int i; Clear(&s[0]); /* Create a set with every */ for ( i = lower; i <= upper; i += 3 ) { /* third possible value, */ Insert(&s[0], i); /* copy it, and make sure */ Exit_If_Error_On("Insert"); /* both sets have the same */ } /* members. */ Copy(&s[0], &s[1]); for ( i = lower; i <= upper; i++ ) if ( Member(&s[0], i) != Member(&s[1], i) ) Exit_Indicating_Failed_Op("Member|Copy"); else Exit_If_Error_On("Member"); } int Count_Of_Elements_Iterated_Over; boolean Iterator(e) int e; { if ( e % 2 != 0 ) /* passed a value that wasn't inserted. */ Exit_Indicating_Failed_Op("Iterate"); Count_Of_Elements_Iterated_Over++; return TRUE; } void Test_Iterate(s, lower, upper) set s[]; int lower, upper; { int i; int Count_Of_Elements_Added; Count_Of_Elements_Added = Count_Of_Elements_Iterated_Over = 0; Clear(&s[0]); for ( i = (lower/2)*2 + 2; i <= upper; i += 2 ) { Insert(&s[0], i); /* Insert all even values */ Exit_If_Error_On("Insert"); /* (except perhaps the */ Count_Of_Elements_Added++; /* first) into the set. */ } Iterate(&s[0], Iterator); Exit_If_Error_On("Iterate"); if ( Count_Of_Elements_Added != Count_Of_Elements_Iterated_Over ) Exit_Indicating_Failed_Op("Iterate"); } void Exit_If_Error_On(operation) char operation[]; { if ( ! Error_Occurred() ) return; printf("%s operation caused an error.\n", operation); exit(1); } void Exit_Indicating_Failed_Op(operation) char operation[]; { printf("%s operation failed to function correctly.\n", operation); exit(1); }