diff options
| -rw-r--r-- | include/gensvm_strutil.h | 2 | ||||
| -rw-r--r-- | src/gensvm_strutil.c | 25 | ||||
| -rw-r--r-- | tests/src/test_gensvm_strutil.c | 268 |
3 files changed, 287 insertions, 8 deletions
diff --git a/include/gensvm_strutil.h b/include/gensvm_strutil.h index efaa5ec..acdd0c0 100644 --- a/include/gensvm_strutil.h +++ b/include/gensvm_strutil.h @@ -19,7 +19,7 @@ bool str_startswith(const char *str, const char *pre); bool str_endswith(const char *str, const char *suf); void next_line(FILE *fid, char *filename); -void get_line(FILE *fid, char *filename, char *buffer); +char *get_line(FILE *fid, char *filename, char *buffer); double get_fmt_double(FILE *fid, char *filename, const char *fmt); long get_fmt_long(FILE *fid, char *filename, const char *fmt); diff --git a/src/gensvm_strutil.c b/src/gensvm_strutil.c index b4c5c54..4b8b37b 100644 --- a/src/gensvm_strutil.c +++ b/src/gensvm_strutil.c @@ -61,17 +61,22 @@ void next_line(FILE *fid, char *filename) * @param[in] filename name of the file * @param[in,out] buffer allocated buffer to read to */ -void get_line(FILE *fid, char *filename, char *buffer) +char *get_line(FILE *fid, char *filename, char *buffer) { - if (fgets(buffer, MAX_LINE_LENGTH, fid) == NULL) { + char *retval = fgets(buffer, MAX_LINE_LENGTH, fid); + if (retval == NULL) { fprintf(stderr, "Error reading file %s\n", filename); - exit(1); } + return retval; } /** * @brief Read a double from file following a format * + * @details + * This function reads a double value from a file. If no value can be found, a + * warning is printed to stderr, and NAN is returned. + * * @param[in] fid File opened for reading * @param[in] filename Name of the file * @param[in] fmt Format containing a float format @@ -80,10 +85,13 @@ void get_line(FILE *fid, char *filename, char *buffer) double get_fmt_double(FILE *fid, char *filename, const char *fmt) { char buffer[MAX_LINE_LENGTH]; - double value; + double value = NAN; + int retval; get_line(fid, filename, buffer); - sscanf(buffer, fmt, &value); + retval = sscanf(buffer, fmt, &value); + if (retval == 0) + fprintf(stderr, "No double read from file.\n"); return value; } @@ -98,10 +106,13 @@ double get_fmt_double(FILE *fid, char *filename, const char *fmt) long get_fmt_long(FILE *fid, char *filename, const char *fmt) { char buffer[MAX_LINE_LENGTH]; - long value; + long value = 0; + int retval; get_line(fid, filename, buffer); - sscanf(buffer, fmt, &value); + retval = sscanf(buffer, fmt, &value); + if (retval == 0) + fprintf(stderr, "No long read from file.\n"); return value; } diff --git a/tests/src/test_gensvm_strutil.c b/tests/src/test_gensvm_strutil.c new file mode 100644 index 0000000..520560f --- /dev/null +++ b/tests/src/test_gensvm_strutil.c @@ -0,0 +1,268 @@ +/** + * @file test_gensvm_strutil.c + * @author Gertjan van den Burg + * @date May, 2016 + * @brief Unit tests for gensvm_strutil.c functions + */ + +#include "minunit.h" +#include "gensvm_strutil.h" + +char *test_str_startswith() +{ + mu_assert(str_startswith("test this string", "test") == true, + "startswith first test failed."); + mu_assert(str_startswith("test this string", "word") == false, + "startswith second test failed."); + return NULL; +} + +char *test_str_endswith() +{ + mu_assert(str_endswith("this is a string", "string") == true, + "endswith first test failed."); + mu_assert(str_endswith("this is a string", "word") == false, + "endswith second test failed."); + return NULL; +} + +char *test_get_line() +{ + char *fname = "test_get_line.txt"; + // prepare the test file + FILE *fid = fopen(fname, "w"); + if (fid == NULL) return "couldn't open test file for get_line"; + fprintf(fid, "first line\n"); + fprintf(fid, "second line\n"); + fclose(fid); + // end preparation + + // start of test code + char buffer[MAX_LINE_LENGTH]; + char *retval = NULL; + fid = fopen(fname, "r"); + retval = get_line(fid, fname, buffer); + mu_assert(retval == buffer, "return value not buffer (1)"); + retval = get_line(fid, fname, buffer); + mu_assert(retval == buffer, "return value not buffer (2)"); + retval = get_line(fid, fname, buffer); + mu_assert(retval == NULL, "return value not NULL"); + + fclose(fid); + // end of test code + + // cleanup + remove(fname); + + return NULL; +} + +char *test_next_line() +{ + char *fname = "test_next_line.txt"; + // prepare the test file + FILE *fid = fopen(fname, "w"); + if (fid == NULL) return "couldn't open test file for next_line"; + fprintf(fid, "first line\n"); + fprintf(fid, "second line\n"); + fprintf(fid, "third line\n"); + fprintf(fid, "fourth line\n"); + fclose(fid); + // end preparation + + // start of test code + char line[60]; + fid = fopen(fname, "r"); + next_line(fid, fname); + fgets(line, 60, fid); + mu_assert(strcmp(line, "second line\n") == 0, "second line unequal"); + next_line(fid, fname); + fgets(line, 60, fid); + mu_assert(strcmp(line, "fourth line\n") == 0, "fourth line unequal"); + fclose(fid); + // end of test code + + // cleanup + remove(fname); + + return NULL; +} + +char *test_get_fmt_double() +{ + char *fname = "test_get_fmt_double.txt"; + // prepare the test file + FILE *fid = fopen(fname, "w"); + if (fid == NULL) return "couldn't open test file for get_fmt_double"; + fprintf(fid, "double = 3.1416\n"); + fprintf(fid, "another double = 42.42\n"); + fprintf(fid, "line without a double\n"); + fclose(fid); + + // start test code // + double value = -1.0; + fid = fopen(fname, "r"); + + value = get_fmt_double(fid, fname, "double = %lf"); + mu_assert(value == 3.1416, "first value wrong"); + + value = get_fmt_double(fid, fname, "another double = %lf"); + mu_assert(value == 42.42, "second value wrong"); + + value = get_fmt_double(fid, fname, "line without a double"); + mu_assert(isnan(value), "third value wrong"); + + fclose(fid); + // end test code // + + // cleanup + remove(fname); + + return NULL; +} + +char *test_get_fmt_long() +{ + char *fname = "test_get_fmt_long.txt"; + // prepare the test file + FILE *fid = fopen(fname, "w"); + if (fid == NULL) return "couldn't open test file for get_fmt_double"; + fprintf(fid, "long = 53161\n"); + fprintf(fid, "another long = 1212\n"); + fprintf(fid, "line without a long\n"); + fclose(fid); + + // start test code // + long value = -1; + fid = fopen(fname, "r"); + + value = get_fmt_long(fid, fname, "long = %li"); + mu_assert(value == 53161, "first value wrong"); + + value = get_fmt_long(fid, fname, "another long = %li"); + mu_assert(value == 1212, "second value wrong"); + + value = get_fmt_long(fid, fname, "line without a long"); + // unfortunately we can't test this properly, a warning will be + // generated but the return value will be 0, which can be a valid + // value. In general therefore, the real test is to see if a warning + // is printed to stderr. + mu_assert(value == 0, "third value wrong") + + fclose(fid); + // end test code // + + // cleanup + remove(fname); + + return NULL; +} + +char *test_all_doubles_str() +{ + char *fname = "test_all_doubles_str.txt"; + // prepare the test file + FILE *fid = fopen(fname, "w"); + if (fid == NULL) return "couldn't open test file for all_doubles_str"; + fprintf(fid, "1.0 2.0 3.0 4.0\n"); + fprintf(fid, "9.1 8.2 7.3\n"); + fprintf(fid, "offset 1.0 2.0\n"); + fclose(fid); + + // start test code // + char buffer[60]; + double *values = Calloc(double, 10); + fid = fopen(fname, "r"); + int nr = -1; + + fgets(buffer, 60, fid); + nr = all_doubles_str(buffer, 0, values); + mu_assert(nr == 4, "incorrect number of doubles (1)"); + mu_assert(values[0] == 1.0, "incorrect first value (1)"); + mu_assert(values[1] == 2.0, "incorrect second value (1)"); + mu_assert(values[2] == 3.0, "incorrect third value (1)"); + mu_assert(values[3] == 4.0, "incorrect fourth value (1)"); + + fgets(buffer, 60, fid); + nr = all_doubles_str(buffer, 0, values); + mu_assert(nr == 3, "incorrect number of doubles (2)"); + mu_assert(values[0] == 9.1, "incorrect first value (2)"); + mu_assert(values[1] == 8.2, "incorrect second value (2)"); + mu_assert(values[2] == 7.3, "incorrect third value (2)"); + + fgets(buffer, 60, fid); + nr = all_doubles_str(buffer, 7, values); + mu_assert(nr == 2, "incorrect number of doubles (3)"); + mu_assert(values[0] == 1.0, "incorrect first value (3)"); + mu_assert(values[1] == 2.0, "incorrect second value (3)"); + // end test code // + + // cleanup + remove(fname); + free(values); + + return NULL; +} + +char *test_all_longs_str() +{ + char *fname = "test_all_longs_str.txt"; + // prepare the test file + FILE *fid = fopen(fname, "w"); + if (fid == NULL) return "couldn't open test file for all_longs_str"; + fprintf(fid, "1 2 3 4\n"); + fprintf(fid, "91 82 73\n"); + fprintf(fid, "offset 10 20\n"); + fclose(fid); + + // start test code // + char buffer[60]; + long *values = Calloc(long, 10); + fid = fopen(fname, "r"); + int nr = -1; + + fgets(buffer, 60, fid); + nr = all_longs_str(buffer, 0, values); + mu_assert(nr == 4, "incorrect number of longs (1)"); + mu_assert(values[0] == 1, "incorrect first value (1)"); + mu_assert(values[1] == 2, "incorrect second value (1)"); + mu_assert(values[2] == 3, "incorrect third value (1)"); + mu_assert(values[3] == 4, "incorrect fourth value (1)"); + + fgets(buffer, 60, fid); + nr = all_longs_str(buffer, 0, values); + mu_assert(nr == 3, "incorrect number of longs (2)"); + mu_assert(values[0] == 91, "incorrect first value (2)"); + mu_assert(values[1] == 82, "incorrect second value (2)"); + mu_assert(values[2] == 73, "incorrect third value (2)"); + + fgets(buffer, 60, fid); + nr = all_longs_str(buffer, 7, values); + mu_assert(nr == 2, "incorrect number of longs (3)"); + mu_assert(values[0] == 10, "incorrect first value (3)"); + mu_assert(values[1] == 20, "incorrect second value (3)"); + // end test code // + + // cleanup + remove(fname); + free(values); + + return NULL; +} + +char *all_tests() +{ + mu_suite_start(); + mu_run_test(test_str_startswith); + mu_run_test(test_str_endswith); + mu_run_test(test_get_line); + mu_run_test(test_next_line); + mu_run_test(test_get_fmt_double); + mu_run_test(test_get_fmt_long); + mu_run_test(test_all_doubles_str); + mu_run_test(test_all_longs_str); + + return NULL; +} + +RUN_TESTS(all_tests); |
