This is tester.m in view mode; [Download] [Up]
//
// overall testing of many of the RCString categories.
// has gets() statements to allow checks for dangling
// pointers every so often.
//
#import <stdio.h>
#import <stdlib.h>
#import <signal.h>
#import <fcntl.h>
#import <string.h>
#import <sys/time.h>
#import <RCString.h>
int igErrorCount = 0;
char *getrandomstring();
int
main(int c, char **v)
{
void xp_test(char *);
void insert_test(char *bpBaseString, char *bpToInsert, int index);
void retrieve_test();
void replace_test();
char *bvLargeString;
char buf[512];
int icCount, iErrorCount, iInsertLocation;
struct timeval sTimeVal;
#ifdef NeXT
int signalHandler();
// install a few signal handlers
signal(SIGSEGV, signalHandler);
signal(SIGBUS, signalHandler);
signal(SIGILL, signalHandler);
// turn on fairly high level of malloc error checking
malloc_debug(8);
#endif NeXT
if (c > 1)
gets(buf);
iErrorCount = igErrorCount;
puts("\ntesting of explicity NULL strings");
xp_test(NULL);
if (iErrorCount != igErrorCount)
printf("committed %d sins\n", igErrorCount - iErrorCount);
if (c > 1)
gets(buf);
iErrorCount = igErrorCount;
puts("\ntesting of zero length strings");
xp_test("");
if (iErrorCount != igErrorCount)
printf("committed %d sins\n", igErrorCount - iErrorCount);
if (c > 1)
gets(buf);
iErrorCount = igErrorCount;
puts("\ntesting of 1-char length strings");
xp_test("a");
if (iErrorCount != igErrorCount)
printf("committed %d sins\n", igErrorCount - iErrorCount);
if (c > 1)
gets(buf);
iErrorCount = igErrorCount;
puts("\ntesting of 2-char length strings");
xp_test("aB");
if (iErrorCount != igErrorCount)
printf("committed %d sins\n", igErrorCount - iErrorCount);
if (c > 1)
gets(buf);
iErrorCount = igErrorCount;
puts("\ntesting of 8973-char length strings");
bvLargeString = malloc(8974);
for (icCount = 0; icCount < 8973; ++icCount)
bvLargeString[icCount] = (icCount % 94) + ' ';
xp_test(bvLargeString);
if (iErrorCount != igErrorCount)
printf("committed %d sins\n", igErrorCount - iErrorCount);
if (c > 1)
gets(buf);
if (igErrorCount)
printf("committed %d sins in allocate/free/empty/compare tests\n",
igErrorCount);
igErrorCount = 0;
puts("\ntesting inserting null strings into other null strings");
iErrorCount = igErrorCount;
// insert_test(char *bpBaseString, char *bpToInsert, int index)
insert_test("", "", 0);
insert_test("", "", -1);
insert_test("", "", 1);
insert_test("", "", 2);
if (iErrorCount != igErrorCount)
printf("null insertion committed %d sins\n", igErrorCount - iErrorCount);
puts("\ntesting inserting null strings into 1-char strings");
iErrorCount = igErrorCount;
// insert_test(char *bpBaseString, char *bpToInsert, int index)
insert_test("", "a", 0);
insert_test("", "a", -1);
insert_test("", "a", 1);
insert_test("B", "", -2);
insert_test("B", "", -1);
insert_test("B", "", 0);
insert_test("B", "", 1);
insert_test("B", "", 2);
if (iErrorCount != igErrorCount)
printf("insertion committed %d sins\n", igErrorCount - iErrorCount);
puts("\ntesting inserting 1-char strings into 1-char strings");
iErrorCount = igErrorCount;
// insert_test(char *bpBaseString, char *bpToInsert, int index)
insert_test("0", "a", -1);
insert_test("0", "a", 0);
insert_test("0", "a", 1);
insert_test("B", "7", -2);
insert_test("B", "7", -1);
insert_test("B", "7", 0);
insert_test("B", "7", 1);
insert_test("B", "7", 2);
if (iErrorCount != igErrorCount)
printf("insertion committed %d sins\n", igErrorCount - iErrorCount);
puts("\ntesting inserting 1-char strings into 2-char strings");
iErrorCount = igErrorCount;
// insert_test(char *bpBaseString, char *bpToInsert, int index)
insert_test("00", "a", -2);
insert_test("00", "a", -1);
insert_test("00", "a", 0);
insert_test("00", "a", 1);
insert_test("00", "a", 2);
insert_test("B", "7F", -2);
insert_test("B", "7F", -1);
insert_test("B", "7F", 0);
insert_test("B", "7F", 1);
insert_test("B", "7F", 2);
if (iErrorCount != igErrorCount)
printf("insertion committed %d sins\n", igErrorCount - iErrorCount);
// redo the "large" string
for (icCount = 0; icCount < 8973; ++icCount)
bvLargeString[icCount] = (icCount % 94) + ' ';
puts("\ntesting inserting large strings into large strings");
iErrorCount = igErrorCount;
insert_test(bvLargeString, bvLargeString, -1);
insert_test(bvLargeString, bvLargeString, 0);
insert_test(bvLargeString, bvLargeString, 1);
insert_test(bvLargeString, bvLargeString, -2);
insert_test(bvLargeString, bvLargeString, -1);
insert_test(bvLargeString, bvLargeString, 0);
insert_test(bvLargeString, bvLargeString, 1);
insert_test(bvLargeString, bvLargeString, 2);
for (icCount = 0; icCount < 5; ++icCount) {
gettimeofday(&sTimeVal, NULL);
iInsertLocation = ((sTimeVal.tv_sec % sTimeVal.tv_usec) % 8973);
printf("inserting a large string at %d\n", iInsertLocation);
insert_test(bvLargeString, bvLargeString, iInsertLocation);
}
if (iErrorCount != igErrorCount)
printf("insertion committed %d sins\n", igErrorCount - iErrorCount);
puts("\ntesting replacement methods");
iErrorCount = igErrorCount;
replace_test();
if (iErrorCount != igErrorCount)
printf("replacement committed %d sins\n", igErrorCount - iErrorCount);
if (c > 1)
gets(buf);
puts("\ntesting retrieval methods");
iErrorCount = igErrorCount;
retrieve_test();
if (iErrorCount != igErrorCount)
printf("retrieval committed %d sins\n", igErrorCount - iErrorCount);
printf("committed %d total sins\n", igErrorCount);
if (c > 1)
gets(buf);
return(0);
}
char *method_strings[3] = { "-new ", "-newFromString:",
"-newFromObject:" };
//
// allocation, deletion, emptying and comparison tests.
//
void
xp_test(char *bpTestValue)
{
int i, j;
RCString *oString1, *oString2, *oString3;
RCString *ovString[3];
RCString *ovCopies[3];
puts("testing of -new methods");
oString1 = [RCString new];
oString2 = [RCString newFromString:bpTestValue];
oString3 = [RCString newFromObject:oString2];
[oString3 copyReference];
if (!oString1) {
fputs(" -new method failed\n", stderr);
++igErrorCount;
}
if (!oString2) {
fputs(" -newFromString method failed\n", stderr);
++igErrorCount;
}
if (!oString3) {
++igErrorCount;
fputs(" -newFromObject method failed\n", stderr);
}
[oString1 free];
[oString2 free];
[oString3 free];
// reference copy counting
puts("\ntesting of reference counting");
ovString[0] = [RCString new];
ovString[1] = [RCString newFromString:bpTestValue];
ovString[2] = [RCString newFromObject:ovString[1]];
[ovString[2] copyReference];
for (j = 0; j < 3; ++j) {
if ([ovString[j] references] != 1) {
printf("%s created object: %d refs (should be 1), internal rep 0x%x\n",
method_strings[j], [ovString[j] references], (unsigned int)[ovString[j] internal]);
++igErrorCount;
}
}
puts("\ncalling copyReference");
for (i = 0; i < 5; ++i) {
for (j = 0; j < 3; ++j) {
[ovString[j] copyReference];
}
}
for (j = 0; j < 3; ++j) {
if ([ovString[j] references] != 1) {
printf("%s created object: %d refs (should be 1), internal rep 0x%x\n",
method_strings[j], [ovString[j] references], (unsigned int)[ovString[j] internal]);
++igErrorCount;
}
}
puts("\ncalling newFromObject: on objects that ought have 1 refs");
for (j = 0; j < 3; ++j)
ovCopies [j] = [RCString newFromObject:ovString[j]];
for (j = 0; j < 3; ++j) {
if ([ovString[j] references] != 2 || [ovCopies[j] references] != 2) {
printf(
"%s created object: %d refs (should be 2), internal rep 0x%x\n",
method_strings[j], [ovString[j] references],
(unsigned int)[ovString[j] internal]);
printf(
"copied object: %d refs (should be 2), internal rep 0x%x\n",
[ovCopies[j] references], (unsigned int)[ovCopies[j] internal]);
++igErrorCount;
}
}
puts("\ncalling copyReference on object copies");
for (j = 0; j < 3; ++j)
[ovCopies [j] copyReference];
for (j = 0; j < 3; ++j) {
if ([ovString[j] references] != 1 || [ovCopies[j] references] != 1) {
printf("%s created object: %d refs (should be 1), internal rep 0x%x\n",
method_strings[j], [ovString[j] references],
(unsigned int)[ovString[j] internal]);
printf(
"copied object: %d refs (should be 1), internal rep 0x%x\n",
[ovCopies[j] references], (unsigned int)[ovCopies[j] internal]);
++igErrorCount;
}
}
for (j = 0; j < 3; ++j) {
[ovString[j] free];
[ovCopies[j] free];
}
puts("testing of -empty methods");
ovString[0] = [RCString new];
ovString[1]= [RCString newFromString:bpTestValue];
ovString[2] = [RCString newFromObject:ovString[1]];
[ovString[2] copyReference];
for (j = 0; j < 3; ++j)
[ovString[j] empty];
for (j = 0; j < 3; ++j) {
if ([ovString[j] length] != 0) {
fprintf(stderr,
"%s created object: %d refs (should be 1), internal rep 0x%x, length NOT 0 after -empty (%u)\n",
method_strings[j], [ovString[j] references], (unsigned int)[ovString[j] internal], [ovString[j] length]);
++igErrorCount;
}
[ovString[j] free];
}
puts("testing of -toUpper method");
ovString[0] = [RCString new];
ovString[1]= [RCString newFromString:bpTestValue];
ovString[2] = [RCString newFromObject:ovString[1]];
[ovString[2] copyReference];
for (j = 0; j < 3; ++j)
[ovString[j] toUpper];
for (j = 0; j < 3; ++j) {
int icIndex, iLength = [ovString[j] length];
char *bpData = [ovString[j] data];
for (icIndex = 0; icIndex < iLength; ++icIndex) {
if (bpData[icIndex] >= 'a' && bpData[icIndex] <= 'z') {
printf(
"%s created object: %d refs (should be 1), internal rep 0x%x\n",
method_strings[j], [ovString[j] references], (unsigned int)[ovString[j] internal]);
printf(
"\tProblem with character \'%c\', at index %d, lowercase when it shouldn't be\n",
bpData[icIndex], icIndex);
++igErrorCount;
break;
}
}
[ovString[j] free];
}
puts("testing of -toLower method");
ovString[0] = [RCString new];
ovString[1]= [RCString newFromString:bpTestValue];
ovString[2] = [RCString newFromObject:ovString[1]];
[ovString[2] copyReference];
for (j = 0; j < 3; ++j)
[ovString[j] toLower];
for (j = 0; j < 3; ++j) {
int icIndex, iLength = [ovString[j] length];
char *bpData = [ovString[j] data];
for (icIndex = 0; icIndex < iLength; ++icIndex) {
if (bpData[icIndex] >= 'A' && bpData[icIndex] <= 'Z') {
printf(
"%s created object: %d refs (should be 1), internal rep 0x%x\n",
method_strings[j], [ovString[j] references], (unsigned int)[ovString[j] internal]);
printf(
"\tProblem with character \'%c\', at index %d, uppercase when it shouldn't be\n",
bpData[icIndex], icIndex);
++igErrorCount;
break;
}
}
[ovString[j] free];
}
puts("testing of case-sensitive -compare methods");
oString1 = [RCString newFromString:bpTestValue];
oString2 = [RCString newFromObject:oString1];
if ([oString1 length] && [oString2 length]
&& [oString1 compareWithObject:oString2]) {
puts("special case (same internal rep) comparison. Should match, but it doesn't");
printf("internal reps at 0x%x and 0x%x\n", (unsigned int)[oString1 internal],
(unsigned int)[oString2 internal]);
++igErrorCount;
}
if ([oString1 length] && strlen(bpTestValue) > 0
&& [oString1 compareWithString:bpTestValue]) {
puts("special case (same ASCIIZ string) comparison. Should match, but it doesn't");
printf("ASCIIZ string: \"%s\", object's string: \"%s\"\n",
bpTestValue?bpTestValue:"NULL", [oString1 data]);
++igErrorCount;
}
// trigger up an object that is guaranteed not to match
// _if_ case is considered.
{
int yUpperCase = 0;
int icCount;
char *bpData = [oString2 data];
for (icCount = 0; icCount < [oString2 length]; ++icCount)
if (bpData[icCount] >= 'A' && bpData[icCount] <= 'Z') {
yUpperCase = 1; // there is an uppercase character
break;
}
// these should both force copy-on-write
if (yUpperCase)
[oString2 toLower];
else
[oString2 toUpper];
}
if ([oString1 length] && [oString2 length]
&& ![oString1 compareWithObject:oString2]) {
puts("Different internal rep comparison. Shouldn't match, but it does");
printf("internal reps at 0x%x and 0x%x\n", (unsigned int)[oString1 internal],
(unsigned int)[oString2 internal]);
printf("object 1's string: \"%s\", object 2's string: \"%s\"\n",
[oString1 data], [oString2 data]);
++igErrorCount;
}
if ([oString1 length] && strlen(bpTestValue) > 0
&& ![oString2 compareWithString:bpTestValue]) {
puts("Comparison to ASCIIZ string. Shouldn't match, but it does");
printf("object's string: \"%s\", ASCIIZ string: \"%s\"\n",
[oString2 data], bpTestValue);
++igErrorCount;
}
puts("testing of case-insensitive -compare methods");
[oString1 caseSensitive:NO];
[oString2 caseSensitive:NO];
oString3 = [RCString newFromObject:oString1];
if ([oString1 compareWithObject:oString3]) {
puts("special case (same internal rep) comparison. Should match, but it doesn't");
printf("internal reps at 0x%x and 0x%x\n", (unsigned int)[oString1 internal],
(unsigned int)[oString2 internal]);
++igErrorCount;
}
if ([oString1 compareWithString:bpTestValue]) {
puts("Comparison to ASCIIZ string. Should match, but it doesn't");
printf("object's string: \"%s\", ASCIIZ string: \"%s\"\n",
[oString2 data], bpTestValue);
++igErrorCount;
}
if ([oString1 compareWithObject:oString2]) {
puts("Different internal rep comparison. Should match, but it doesn't");
printf("internal reps at 0x%x and 0x%x\n", (unsigned int)[oString1 internal],
(unsigned int)[oString2 internal]);
printf("object 1's string: \"%s\", object 2's string: \"%s\"\n",
[oString1 data], [oString2 data]);
++igErrorCount;
}
if ([oString2 compareWithString:bpTestValue]) {
puts("Comparison to ASCIIZ string. Should match, but it doesn't");
printf("object's string: \"%s\", ASCIIZ string: \"%s\"\n",
[oString2 data], bpTestValue);
++igErrorCount;
}
[oString1 free];
[oString2 free];
[oString3 free];
}
void
insert_test(char *bpBaseString, char *bpToInsert, int index)
{
RCString *oStringAppend;
RCString *oStringPrepend;
RCString *oStringMiddle;
char *bpTmpBuffer;
int icCnt, iSize;
iSize = strlen(bpBaseString) + strlen(bpToInsert) + 1;
bpTmpBuffer = malloc(iSize);
bzero(bpTmpBuffer, iSize);
oStringAppend = [RCString newFromString:bpBaseString];
[oStringAppend appendString:bpToInsert];
strcpy(bpTmpBuffer, bpBaseString);
strcat(bpTmpBuffer, bpToInsert);
if (strcmp(bpTmpBuffer, [oStringAppend data])) {
++igErrorCount;
printf("tried to append \"%s\" to \"%s\": should be \"%s\", is \"%s\"\n",
bpToInsert, bpBaseString, bpTmpBuffer, [oStringAppend data]);
}
bzero(bpTmpBuffer, iSize);
oStringPrepend = [RCString newFromString:bpBaseString];
[oStringPrepend prependString:bpToInsert];
strcpy(bpTmpBuffer, bpToInsert);
strcat(bpTmpBuffer, bpBaseString);
if (strcmp(bpTmpBuffer, [oStringPrepend data])) {
++igErrorCount;
printf(
"tried to prepend \"%s\" to \"%s\": should be \"%s\", is \"%s\"\n",
bpToInsert, bpBaseString, bpTmpBuffer, [oStringPrepend data]);
}
bzero(bpTmpBuffer, iSize);
oStringMiddle = [RCString newFromString:bpBaseString];
[oStringMiddle insertString:bpToInsert at:index];
if (index >= 0) {
if (index > strlen(bpBaseString))
index = strlen(bpBaseString);
for (icCnt = 0; icCnt < index; ++icCnt)
bpTmpBuffer[icCnt] = bpBaseString[icCnt];
strcat(&bpTmpBuffer[index], bpToInsert);
if (index < strlen(bpBaseString))
strcat(bpTmpBuffer, &bpBaseString[index]);
} else {
strcat(bpTmpBuffer, bpBaseString);
}
if (strcmp(bpTmpBuffer, [oStringMiddle data])) {
++igErrorCount;
printf("tried to stick \"%s\" in \"%s\": should be \"%s\", is \"%s\"\n",
bpToInsert, bpBaseString, bpTmpBuffer, [oStringMiddle data]);
}
[oStringAppend free];
[oStringPrepend free];
[oStringMiddle free];
free(bpTmpBuffer);
}
void
replace_test()
{
RCString *o1, *o2;
struct srep *sTmp;
char *bpOldString, *bpNewString;
o1 = [RCString new];
sTmp = [o1 internal];
[o1 replaceWithAsciiString:NULL];
if (sTmp != [o1 internal]) {
if (strlen([o1 data]) != 0) {
puts("replacing (empty string) object's internal string with a NULL");
++igErrorCount;
}
}
[o1 free];
bpOldString = getrandomstring();
o1 = [RCString newFromString:bpOldString];
sTmp = [o1 internal];
bpNewString = getrandomstring();
[o1 replaceWithAsciiString:bpNewString];
if (sTmp != [o1 internal]) {
if (![o1 compareWithString:bpOldString]) {
puts("replacing object's internal string with a another string");
++igErrorCount;
}
}
[o1 free];
free(bpOldString);
free(bpNewString);
bpOldString = getrandomstring();
o1 = [RCString newFromString:bpOldString];
o2 = [RCString newFromObject:o1];
bpNewString = getrandomstring();
[o2 replaceWithAsciiString:bpNewString];
if ([o1 internal] == [o2 internal]) {
puts("replaceWithAsciiString: failure");
++igErrorCount;
}
[o1 replaceWithObject:o2];
if ([o1 internal] != [o2 internal]) {
puts("replaceWithObject: failure");
++igErrorCount;
}
[o1 free];
[o2 free];
free(bpOldString);
free(bpNewString);
return;
}
void
retrieve_test()
{
char *bpTestString = getrandomstring();
RCString *o1 = [RCString newFromString:bpTestString];
if (o1) {
char *bpSubString;
RCString *oSubObject;
int iLength, iMaxLength;
// check entire string
iMaxLength = strlen(bpTestString);
bpSubString = [o1 subStringAt:0 extent:iMaxLength];
if (strcmp(bpSubString, bpTestString)) {
puts("comparison of entire string from subStringAt: method failed");
++igErrorCount;
}
oSubObject = [o1 subObjectAt:0 extent:iMaxLength];
if (oSubObject) {
if ([o1 compareWithObject:oSubObject]
|| [oSubObject compareWithObject:o1]) {
puts("comparison of entire object with subobject failed");
++igErrorCount;
}
[oSubObject free];
} else {
puts("subObjectAt:extent: method didn't produce an object");
++igErrorCount;
}
if (bpSubString) free(bpSubString);
// check all substrings, beginning at start of string
for (iLength = 1; iLength < iMaxLength; iLength += 10) {
bpSubString = [o1 subStringAt:0 extent:iLength];
if (strncmp(bpSubString, bpTestString, iLength)) {
printf("substring of length %d, beginning at start of string doesn't match\n", iLength);
free(bpSubString);
++igErrorCount;
break;
}
oSubObject = [o1 subObjectAt:0 extent:iLength];
if (oSubObject) {
if (strncmp([o1 data], [oSubObject data], iLength)) {
puts("comparison of entire object with subobject failed");
printf("comparison of object with subobject for length %d failed", iLength);
++igErrorCount;
}
[oSubObject free];
} else {
printf("subObjectAt:extent: method didn't produce an object for length %d", iLength);
++igErrorCount;
}
free(bpSubString);
}
// check all substrings, from end of string
for (iLength = iMaxLength; iLength > 1; iLength -= 10) {
bpSubString = [o1 subStringAt:(iMaxLength - iLength) extent:iLength];
if (strncmp(bpSubString, &bpTestString[iMaxLength - iLength], iLength)) {
printf("substring of length %d, beginning at start of string doesn't match\n", iLength);
free(bpSubString);
++igErrorCount;
break;
}
oSubObject = [o1 subObjectAt:(iMaxLength - iLength) extent:iLength];
if (oSubObject) {
if (strncmp([oSubObject data],
&([o1 data][iMaxLength - iLength]), iLength)) {
printf("comparison of object with subobject for length %d failed\n", iLength);
++igErrorCount;
}
[oSubObject free];
} else {
printf("subObjectAt:extent: method didn't produce an object for length %d\n", iLength);
++igErrorCount;
}
free(bpSubString);
}
[o1 free];
}
free(bpTestString);
}
#ifdef NeXT
int
signalHandler(int something)
{
printf("signalHandler(%d) (0x%x)\n", something, (unsigned int)something);
exit(0);
}
#endif
char *
getrandomstring()
{
struct timeval sTimeVal;
int iLength, iBegin, icIndex;
char *bpRandStr;
gettimeofday(&sTimeVal, NULL);
iLength = ((sTimeVal.tv_sec % sTimeVal.tv_usec) % 8192);
iBegin = (sTimeVal.tv_sec + sTimeVal.tv_usec)%26;
bpRandStr = malloc(iLength + 1);
if (bpRandStr) {
for (icIndex = 0; icIndex < iLength; ++icIndex)
bpRandStr[icIndex] = (iBegin++ % 0x5f) + ' ';
bpRandStr[iLength] = '\0';
}
return bpRandStr;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.