/* * Testing harness for string buffer implementations. See the API * in string_buffer.h. * * Copyright Mark A. Sheldon, Spring 2007 * * Known bug: The tests require a file, whose entire contents are * read into a string_buffer. If this file cannot be read, some * subsequent tests will fail even if the string_buffer code is * correct. */ #include #include #include #include #include "string_buffer.h" #define MAXFILENAME 256 #define NUMCOMMANDS 8 #define PFTEST(cond) ((cond) ? "passed" : "failed") static strbuff_t sb = NULL; void test_case(char *msg, char *status) { printf(status); printf(": "); printf(msg); printf("\n"); } void test_mk_strbuff() { strbuff_t sb1, sb2; char *s1, *s2; sb1 = mk_strbuff(); sb2 = mk_strbuff(); test_case("two string buffers, sb1 != sb2", PFTEST(sb1 != sb2)); if (sb1 == NULL) fprintf(stderr, "Unable to allocate sb1\n"); test_case("sb1 initial state", PFTEST((strbuff_size(sb1) == 0) && (strbuff_capacity(sb1) == 1) && ((s1 = strbuff_to_string(sb1)) != NULL) && (strlen(s1) == 0) && ((s2 = strbuff_to_string(sb2)) != s1))); free(s1); free(s2); strbuff_destroy(sb1); strbuff_destroy(sb2); } void test_strbuff_size_and_capacity() { test_case("size and capacity of NULL => -1", PFTEST((strbuff_size(NULL) == -1) && (strbuff_capacity(NULL) == -1))); /* fprintf(stderr, "sb1: size = %d, capacity = %d, contents = %s\n\n", strbuff_size(sb1), strbuff_capacity(sb1), strbuff_to_string(sb1)); */ } void test_strbuff_append() { char filename[MAXFILENAME]; FILE *infile; int c, nchars = 0; char *s; if (sb != NULL) strbuff_destroy(sb); sb = mk_strbuff(); test_case("strbuff_append(NULL, 'c') == EINVAL", PFTEST(strbuff_append(NULL, 'c') == EINVAL)); printf("Enter a file name: "); scanf("%s", filename); if ((infile = fopen(filename, "r")) == NULL) { fprintf(stderr, "unable to open file: %s\n", filename); return; } /* generate output every 5 characters */ while ((c = fgetc(infile)) != EOF) { strbuff_append(sb, c); if ((nchars++ % 5) == 0) { fprintf(stderr, "nchars = %d, size = %d, ", nchars, strbuff_size(sb)); fprintf(stderr, "sb1 capacity = %d\n", strbuff_capacity(sb)); } } test_case("testing sb size == nchars", PFTEST(strbuff_size(sb) == nchars)); s = strbuff_to_string(sb); fprintf(stderr, "%s\n", s); /* in case s has embedded %'s */ free(s); } void test_strbuff_to_string() { char *s1, *s2; if (sb == NULL) test_strbuff_append(); test_case("strbuff_to_string(NULL) == NULL", PFTEST(strbuff_to_string(NULL) == NULL)); s1 = strbuff_to_string(sb); s2 = strbuff_to_string(sb); test_case("strbuff_to_string() results equal but not eq", PFTEST((s1 != NULL) && (s2 != NULL) && (s1 != s2) && (strcmp(s1, s2) == 0))); free(s1); s2[3] = '\0'; s1 = strbuff_to_string(sb); test_case("strbuff_to_string() result disjoint w/ contents", PFTEST(strcmp(s1, s2) != 0)); free(s1); free(s2); } void test_strbuff_append_str() { char *s1, *s2; test_case("strbuff_append_str() => EINVAL with arg NULL", PFTEST((strbuff_append_str(NULL, "foo") == EINVAL) && (strbuff_append_str(sb, NULL) == EINVAL))); if (sb == NULL) test_strbuff_append(); s1 = strbuff_to_string(sb); s2 = malloc(2 * strbuff_size(sb) + 1); if (s2 == NULL) { fprintf(stderr, "Unable to allocate 2*strbuff_size(sb)\n"); return; } strcpy(s2, s1); strcat(s2, s1); test_case("strbuff_append_str(sb, s1) returns 0", PFTEST(strbuff_append_str(sb, s1) == 0)); test_case("strbuff_append_str(sb, s1) doubles sb size", PFTEST(strbuff_size(sb) == 2 * strlen(s1))); free(s1); s1 = strbuff_to_string(sb); test_case("correct result in contents", PFTEST(strcmp(s1, s2) == 0)); free(s1); free(s2); /* need to test for independent mutation */ } void test_strbuff_truncate() { int cap; char *s; test_case("truncating NULL sb pointer returns EINVAL", PFTEST(strbuff_truncate(NULL, 0) == EINVAL)); test_case("truncating sb to negative size returns EINVAL", PFTEST(strbuff_truncate(sb, -1) == EINVAL)); if (sb == NULL) { test_strbuff_append(); } cap = strbuff_capacity(sb); s = strbuff_to_string(sb); test_case("strbuff_truncate() works", PFTEST((strbuff_truncate(sb, 10) == 0) && (strbuff_size(sb) == 10) && (strbuff_capacity(sb) == cap) && (memcmp(s, strbuff_to_string(sb), 10) == 0))); } void test_strbuff_getchar_setchar() { strbuff_t sb2 = mk_strbuff(); char c; int i, chars_correct = 1; test_case("strbuff_getchar(NULL, 0) == -1", PFTEST(strbuff_getchar(NULL, 0) == -1)); if (strbuff_append_str(sb2, "01234567") != 0) { fprintf(stderr, "appending 8-char string failed\n"); return; } test_case("8 chars in sb2", PFTEST(strbuff_size(sb2) == 8)); test_case("strbuff_getchar(sb, -2) == -1", PFTEST(strbuff_getchar(sb, -2) == -1)); test_case("strbuff_getchar(sb, toomuch) == -1", PFTEST(strbuff_getchar(sb2, 8) == -1)); for (i = 0, c = '0'; i < 8; i++, c++) if (strbuff_getchar(sb2, i) != c) { chars_correct = 0; break; } test_case("strbuff_getchar() works", PFTEST(chars_correct)); test_case("strbuff_setchar(NULL, 'c', 0) == -1", PFTEST(strbuff_setchar(NULL, 'c', 0) == -1)); test_case("strbuff_setchar(sb, 'c', -2) == -1", PFTEST(strbuff_setchar(sb, 'c', -2) == -1)); test_case("strbuff_setchar(sb, toomuch) == -1", PFTEST(strbuff_setchar(sb2, 'c', 8) == -1)); for (i = 0, c = 'a'; i < 8; i++, c++) if (strbuff_setchar(sb2, c, i) == -1) { fprintf(stderr, "Unable to put char\n"); return; } for (chars_correct = 1, i = 0, c = 'a'; i < 8; i++, c++) if (strbuff_getchar(sb2, i) != c) { chars_correct = 0; break; } test_case("strbuff_setchar() works", PFTEST(chars_correct)); } void test_all() { test_mk_strbuff(); test_strbuff_size_and_capacity(); test_strbuff_append(); test_strbuff_to_string(); test_strbuff_append_str(); test_strbuff_getchar_setchar(); test_strbuff_truncate(); } void print_options() { printf("0: all\n"); printf("1: test_mk_strbuff()\n"); printf("2: test_strbuff_size_and_capacity()\n"); printf("3: test_strbuff_append()\n"); printf("4: test_strbuff_to_string()\n"); printf("5: test_strbuff_append_str()\n"); printf("6: test_strbuff_getchar_setchar()\n"); printf("7: test_strbuff_truncate()\n"); printf("\nq: quit\n\n: "); } void (*dispatch_table[])() = { test_all, test_mk_strbuff, test_strbuff_size_and_capacity, test_strbuff_append, test_strbuff_to_string, test_strbuff_append_str, test_strbuff_getchar_setchar, test_strbuff_truncate }; int main (int argc, char **argv) { int command; print_options(); while (1) { command = getchar(); if ((command == EOF) || command == 'q') break; command = command - '0'; if ((command < 0) || command >= NUMCOMMANDS) { printf("\r?: "); continue; } dispatch_table[command](); print_options(); } /* Can't really test strbuff_destroy(), though should check it * doesn't blow up if passed NULL. */ strbuff_destroy(sb); return 0; }