diff options
author | Joseph Hunkeler <jhunkeler@users.noreply.github.com> | 2020-05-26 14:43:00 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-26 14:43:00 -0400 |
commit | df0686fb8b6fefebda0548d39caad2622e2bce89 (patch) | |
tree | cbd2d92667a0ab45221a220948f6ee33b2926a1c | |
parent | c205840e737b23614a686a9675b896106cee5c64 (diff) | |
parent | 065d39bff58c02719abf5a710b22d8355ff1b19d (diff) | |
download | spmc-df0686fb8b6fefebda0548d39caad2622e2bce89.tar.gz |
Merge pull request #38 from jhunkeler/from-file
From file
-rw-r--r-- | include/error_handler.h | 2 | ||||
-rw-r--r-- | include/fs.h | 3 | ||||
-rw-r--r-- | include/mirrors.h | 1 | ||||
-rw-r--r-- | include/strlist.h | 3 | ||||
-rw-r--r-- | lib/error_handler.c | 5 | ||||
-rw-r--r-- | lib/fs.c | 98 | ||||
-rw-r--r-- | lib/install.c | 16 | ||||
-rw-r--r-- | lib/mirrors.c | 81 | ||||
-rw-r--r-- | lib/strlist.c | 115 | ||||
-rw-r--r-- | src/spm.c | 56 | ||||
-rw-r--r-- | tests/test_strlist.c | 60 |
11 files changed, 313 insertions, 127 deletions
diff --git a/include/error_handler.h b/include/error_handler.h index eaf6420..5e1639b 100644 --- a/include/error_handler.h +++ b/include/error_handler.h @@ -18,6 +18,7 @@ #define SPM_ERR_MANIFEST_EMPTY _SPM_ERR(8) // manifest file has no data #define SPM_ERR_PARSE _SPM_ERR(9) // general parsing error #define SPM_ERR_NOT_IMPLEMENTED _SPM_ERR(10) // not implemented (does exist on this platform) +#define SPM_ERR_FETCH _SPM_ERR(11) // failed to download data (non-package) extern int spmerrno; extern const char *SPM_ERR_STRING[]; @@ -25,5 +26,6 @@ extern const char *SPM_ERR_STRING[]; void spmerrno_cause(const char *reason); char *spm_strerror(int code); void spm_perror(const char *msg); +void spm_die(void); #endif //SPM_ERROR_HANDLER_H diff --git a/include/fs.h b/include/fs.h index c41b649..81acd92 100644 --- a/include/fs.h +++ b/include/fs.h @@ -41,6 +41,5 @@ char *human_readable_size(uint64_t n); char *expandpath(const char *_path); char *spm_mkdtemp(const char *base, const char *name, const char *extended_path); int touch(const char *path); - - +char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn); #endif //SPM_FSTREE_H diff --git a/include/mirrors.h b/include/mirrors.h index c9c5c23..dd4b256 100644 --- a/include/mirrors.h +++ b/include/mirrors.h @@ -7,7 +7,6 @@ #define SPM_MIRROR_MAX 0xff #define SPM_MIRROR_FILENAME "mirrorlist" -char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn); char **mirror_list(const char *filename); void mirror_list_free(char **m); void mirror_clone(Manifest *info, char *dest); diff --git a/include/strlist.h b/include/strlist.h index 76b6d5f..55a784f 100644 --- a/include/strlist.h +++ b/include/strlist.h @@ -4,6 +4,7 @@ */ #ifndef SPM_STRLIST_H #define SPM_STRLIST_H +#include "metadata.h" typedef struct { size_t num_alloc; @@ -26,13 +27,13 @@ unsigned short strlist_item_as_ushort(StrList *pStrList, size_t index); short strlist_item_as_short(StrList *pStrList, size_t index); unsigned char strlist_item_as_uchar(StrList *pStrList, size_t index); char strlist_item_as_char(StrList *pStrList, size_t index); -unsigned char strlist_item_as_uchar(StrList *pStrList, size_t index); char *strlist_item_as_str(StrList *pStrList, size_t index); char *strlist_item(StrList *pStrList, size_t index); void strlist_set(StrList *pStrList, size_t index, char *value); size_t strlist_count(StrList *pStrList); void strlist_reverse(StrList *pStrList); void strlist_sort(StrList *pStrList, unsigned int mode); +int strlist_append_file(StrList *pStrList, char *path, ReaderFn *readerFn); void strlist_append_strlist(StrList *pStrList1, StrList *pStrList2); void strlist_append(StrList *pStrList, char *str); StrList *strlist_copy(StrList *pStrList); diff --git a/lib/error_handler.c b/lib/error_handler.c index 2ccb4e7..5130f3a 100644 --- a/lib/error_handler.c +++ b/lib/error_handler.c @@ -15,6 +15,7 @@ const char *SPM_ERR_STRING[] = { "Manifest has no data", "Parsing error", "Not implemented", + "Failed to fetch data", NULL, }; @@ -55,3 +56,7 @@ void spm_perror(const char *msg) { fprintf(stderr, "%s: %s\n", msg ? msg : "", spm_strerror(spmerrno)); } +void spm_die(void) { + spm_perror("FATAL"); + exit(1); +} @@ -641,3 +641,101 @@ char *spm_mkdtemp(const char *base, const char *name, const char *extended_path) return 0; } + +char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn) { + FILE *fp = NULL; + char **result = NULL; + char *buffer = NULL; + size_t lines = 0; + int use_stdin = 0; + + if (strcmp(filename, "-") == 0) { + use_stdin = 1; + } + + if (use_stdin) { + fp = stdin; + } else { + fp = fopen(filename, "r"); + } + + if (fp == NULL) { + perror(filename); + fprintf(SYSERROR); + return NULL; + } + + // Allocate buffer + if ((buffer = calloc(BUFSIZ, sizeof(char))) == NULL) { + perror("line buffer"); + fprintf(SYSERROR); + if (!use_stdin) { + fclose(fp); + } + return NULL; + } + + // count number the of lines in the file + while ((fgets(buffer, BUFSIZ - 1, fp)) != NULL) { + lines++; + } + + if (!lines) { + free(buffer); + if (!use_stdin) { + fclose(fp); + } + return NULL; + } + + rewind(fp); + + // Handle invalid start offset + if (start > lines) { + start = 0; + } + + // Adjust line count when start offset is non-zero + if (start != 0 && start < lines) { + lines -= start; + } + + + // Handle minimum and maximum limits + if (limit == 0 || limit > lines) { + limit = lines; + } + + // Populate results array + result = calloc(limit + 1, sizeof(char *)); + for (size_t i = start; i < limit; i++) { + if (i < start) { + continue; + } + + if (fgets(buffer, BUFSIZ - 1, fp) == NULL) { + break; + } + + if (readerFn != NULL) { + int status = readerFn(i - start, &buffer); + // A status greater than zero indicates we should ignore this line entirely and "continue" + // A status less than zero indicates we should "break" + // A zero status proceeds normally + if (status > 0) { + i--; + continue; + } else if (status < 0) { + break; + } + } + result[i] = strdup(buffer); + memset(buffer, '\0', BUFSIZ); + } + + free(buffer); + if (!use_stdin) { + fclose(fp); + } + return result; +}
\ No newline at end of file diff --git a/lib/install.c b/lib/install.c index 9fb80c2..282c662 100644 --- a/lib/install.c +++ b/lib/install.c @@ -201,16 +201,24 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { ManifestPackage **requirements = NULL; char source[PATH_MAX]; char *tmpdir = NULL; + size_t package_count; + + package_count = strlist_count(packages); + if (package_count == 0) { + spmerrno = SPM_ERR_PKG_NOT_FOUND; + spmerrno_cause("EMPTY PACKAGE LIST"); + return -1; + } // Produce a dependency tree from requested package(s) - for (size_t i = 0; i < strlist_count(packages); i++) { + for (size_t i = 0; i < package_count; i++) { char *item = strlist_item(packages, i); // Does the package exist in the manifest? if (manifestlist_search(mf, item) == NULL) { spmerrno = SPM_ERR_PKG_NOT_FOUND; spmerrno_cause(item); - break; + return -1; } requirements = resolve_dependencies(mf, item); @@ -221,10 +229,6 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { } } - if (spmerrno) { - return -1; - } - tmpdir = spm_mkdtemp(TMP_DIR, "spm_destroot", NULL); if (tmpdir == NULL) { perror("Could not create temporary destination root"); diff --git a/lib/mirrors.c b/lib/mirrors.c index 6bc7aed..1c51845 100644 --- a/lib/mirrors.c +++ b/lib/mirrors.c @@ -1,87 +1,6 @@ #include "spm.h" #include "url.h" -char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn) { - FILE *fp = NULL; - char **result = NULL; - char *buffer = NULL; - size_t lines = 0; - - if ((fp = fopen(filename, "r")) == NULL) { - perror(filename); - fprintf(SYSERROR); - return NULL; - } - - // Allocate buffer - if ((buffer = calloc(BUFSIZ, sizeof(char))) == NULL) { - perror("line buffer"); - fprintf(SYSERROR); - fclose(fp); - return NULL; - } - - // count number the of lines in the file - while ((fgets(buffer, BUFSIZ - 1, fp)) != NULL) { - lines++; - } - - if (!lines) { - free(buffer); - fclose(fp); - return NULL; - } - - rewind(fp); - - // Handle invalid start offset - if (start > lines) { - start = 0; - } - - // Adjust line count when start offset is non-zero - if (start != 0 && start < lines) { - lines -= start; - } - - - // Handle minimum and maximum limits - if (limit == 0 || limit > lines) { - limit = lines; - } - - // Populate results array - result = calloc(limit + 1, sizeof(char *)); - for (size_t i = start; i < limit; i++) { - if (i < start) { - continue; - } - - if (fgets(buffer, BUFSIZ - 1, fp) == NULL) { - break; - } - - if (readerFn != NULL) { - int status = readerFn(i - start, &buffer); - // A status greater than zero indicates we should ignore this line entirely and "continue" - // A status less than zero indicates we should "break" - // A zero status proceeds normally - if (status > 0) { - i--; - continue; - } else if (status < 0) { - break; - } - } - result[i] = strdup(buffer); - memset(buffer, '\0', BUFSIZ); - } - - free(buffer); - fclose(fp); - return result; -} - /** * * @param filename diff --git a/lib/strlist.c b/lib/strlist.c index aac2755..f90cce4 100644 --- a/lib/strlist.c +++ b/lib/strlist.c @@ -4,6 +4,7 @@ */ #include "spm.h" #include "strlist.h" +#include "url.h" /** * @@ -46,21 +47,98 @@ void strlist_append(StrList *pStrList, char *str) { pStrList->num_alloc++; } +static int reader_strlist_append_file(size_t lineno, char **line) { + (void)(lineno); // unused parameter + (void)(line); // unused parameter + return 0; +} + /** - * Produce a new copy of a `StrList` - * @param pStrList `StrList` - * @return `StrList` copy + * Append lines from a local file or remote URL (HTTP/s only) + * @param pStrList + * @param path file path or HTTP/s address + * @param readerFn pointer to a reader function (use NULL to retrieve all data) + * @return 0=success 1=no data, -1=error (spmerrno set) */ -StrList *strlist_copy(StrList *pStrList) { - StrList *result = strlist_init(); - if (pStrList == NULL || result == NULL) { - return NULL; +int strlist_append_file(StrList *pStrList, char *_path, ReaderFn *readerFn) { + int retval = 0; + int is_remote = 0; + char *path = NULL; + char *filename = NULL; + char *from_file_tmpdir = NULL; + char **data = NULL; + + if (readerFn == NULL) { + readerFn = reader_strlist_append_file; } - for (size_t i = 0; i < strlist_count(pStrList); i++) { - strlist_append(result, strlist_item(pStrList, i)); + path = strdup(_path); + if (path == NULL) { + spmerrno = errno; + retval = -1; + goto fatal; } - return result; + + is_remote = (startswith(path, "http") || startswith(path, "https")); + if (is_remote) { + long response = 0; + char *fetched = NULL; + from_file_tmpdir = spm_mkdtemp(TMP_DIR, __FUNCTION__, NULL); + + if (from_file_tmpdir == NULL) { + spmerrno = errno; + spmerrno_cause("file_from temp directory"); + retval = -1; + goto fatal; + } + + fetched = join((char *[]){from_file_tmpdir, basename(path), NULL}, DIRSEPS); + if ((response = fetch(path, fetched)) >= 400) { + spmerrno = SPM_ERR_FETCH; + char cause[PATH_MAX]; + sprintf(cause, "HTTP(%ld): %s: %s", response, http_response_str(response), path); + spmerrno_cause(cause); + retval = -1; + goto fatal; + } + + filename = strdup(fetched); + free(fetched); + } else { + filename = expandpath(path); + } + + if (filename == NULL) { + spmerrno = errno; + retval = -1; + goto fatal; + } + + data = file_readlines(filename, 0, 0, readerFn); + if (data == NULL) { + retval = 1; + goto fatal; + } + + for (size_t record = 0; data[record] != NULL; record++) { + strlist_append(pStrList, data[record]); + free(data[record]); + } + free(data); + +fatal: + if (from_file_tmpdir != NULL) { + rmdirs(from_file_tmpdir); + free(from_file_tmpdir); + } + if (filename != NULL) { + free(filename); + } + if (path != NULL) { + free(path); + } + + return retval; } /** @@ -83,6 +161,23 @@ void strlist_append_strlist(StrList *pStrList1, StrList *pStrList2) { } /** + * Produce a new copy of a `StrList` + * @param pStrList `StrList` + * @return `StrList` copy + */ +StrList *strlist_copy(StrList *pStrList) { + StrList *result = strlist_init(); + if (pStrList == NULL || result == NULL) { + return NULL; + } + + for (size_t i = 0; i < strlist_count(pStrList); i++) { + strlist_append(result, strlist_item(pStrList, i)); + } + return result; +} + +/** * Remove a record by index from a `StrList` * @param pStrList * @param index @@ -10,8 +10,9 @@ int RUNTIME_INSTALL = 0; int RUNTIME_ROOTDIR = 0; int RUNTIME_LIST = 0; int RUNTIME_SEARCH = 0; +char *program_name = NULL; -void usage(const char *program_name) { +void usage(void) { printf("usage: %s [-hVvBIRrmMLS]\n" " -h, --help show this help message\n" " -V, --version show version\n" @@ -30,8 +31,18 @@ void usage(const char *program_name) { } extern spm_vars SPM_GLOBAL; + +static int reader_install_strlist_append_file(size_t lineno, char **line) { + (void)(lineno); // unused parameter + (*line) = strip((*line)); + if (isempty((*line)) || startswith((*line), "#") || startswith((*line), ";") || startswith((*line), "//")) { + return 1; // indicate "continue" + } + return 0; // indicate "ok" +} + int main(int argc, char *argv[], char *arge[]) { - char *program_name = strdup(argv[0]); + program_name = strdup(argv[0]); // not much to see here yet // at the moment this will all be random tests, for better or worse @@ -53,7 +64,7 @@ int main(int argc, char *argv[], char *arge[]) { memset(package_search_str, '\0', PATH_MAX); if (argc < 2) { - usage(program_name); + usage(); exit(1); } @@ -66,7 +77,7 @@ int main(int argc, char *argv[], char *arge[]) { // options if (*arg == '-' || strncmp(arg, "--", 2) == 0) { if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { - usage(program_name); + usage(); exit(0); } else if (strcmp(arg, "-V") == 0 || strcmp(arg, "--version") == 0) { @@ -85,7 +96,7 @@ int main(int argc, char *argv[], char *arge[]) { else if (strcmp(arg, "-m") == 0 || strcmp(arg, "--manifest") == 0) { if (arg_next == NULL) { fprintf(stderr, "-m|--manifest requires a directory path\n"); - usage(program_name); + usage(); exit(1); } manifestlist_append(mf, arg_next); @@ -116,7 +127,7 @@ int main(int argc, char *argv[], char *arge[]) { RUNTIME_SEARCH = 1; if (arg_next == NULL) { fprintf(stderr, "--search requires a package name\n"); - usage(program_name); + usage(); exit(1); } strncpy(package_search_str, arg_next, strlen(arg_next)); @@ -126,7 +137,7 @@ int main(int argc, char *argv[], char *arge[]) { RUNTIME_ROOTDIR = 1; if (!arg_next) { fprintf(stderr, "-r|--root requires a path\n"); - usage(program_name); + usage(); exit(1); } @@ -150,12 +161,29 @@ int main(int argc, char *argv[], char *arge[]) { } if ((argc - i) == 0) { fprintf(stderr, "-R|--remove requires at least one package\n"); - usage(program_name); + usage(); exit(1); } strlist_append(packages, argv[i]); } } + else if (strcmp(arg, "-F") == 0 || strcmp(arg, "--from-file") == 0) { + RUNTIME_INSTALL = 1; + i++; + char *next = argv[i]; + int retval = 0; + + if (next == NULL || startswith(next, "--")) { // do not trap '-' (stdin) + fprintf(stderr, "-F|--from-file requires a file path\n"); + usage(); + exit(1); + } + + retval = strlist_append_file(packages, next, reader_install_strlist_append_file); + if (retval < 0) { + spm_die(); + } + } else if (strcmp(arg, "-I") == 0 || strcmp(arg, "--install") == 0) { RUNTIME_INSTALL = 1; for (int p = 0; i < argc; p++) { @@ -167,7 +195,7 @@ int main(int argc, char *argv[], char *arge[]) { } if ((argc - i) == 0) { fprintf(stderr, "-I|--install requires at least one package\n"); - usage(program_name); + usage(); exit(1); } strlist_append(packages, next); @@ -176,11 +204,15 @@ int main(int argc, char *argv[], char *arge[]) { } else { printf("Unknown option: %s\n", arg); - usage(program_name); + usage(); exit(1); } } + if (spmerrno) { + spm_die(); + } + // Apply some default manifest locations; unless the user passes -M|--override-manifests if (override_manifests == 0) { // Remote package manifests have priority over the local package store @@ -196,11 +228,11 @@ int main(int argc, char *argv[], char *arge[]) { if (!RUNTIME_ROOTDIR && RUNTIME_INSTALL) { fprintf(stderr, "-r|--root requires -I|--install\n"); - usage(program_name); + usage(); exit(1); } else if (!RUNTIME_ROOTDIR && RUNTIME_REMOVE) { fprintf(stderr, "-r|--root requires -R|--remove\n"); - usage(program_name); + usage(); exit(1); } diff --git a/tests/test_strlist.c b/tests/test_strlist.c index fc1ec4b..f5463dc 100644 --- a/tests/test_strlist.c +++ b/tests/test_strlist.c @@ -41,6 +41,11 @@ enum truthValue { uint64_max, }; +char *testfile_truth[] = { + "a", "b", "c", "d", "e", "f", "g", "h", + NULL, +}; + int main(int argc, char *argv[]) { const char *storyFmt = "expected story: '%s', but got '%s'\n"; @@ -48,13 +53,15 @@ int main(int argc, char *argv[]) { union TestValue testValue = {0,}; StrList *strList = NULL; StrList *strListCopy = NULL; - StrList *strListNumbers = NULL; StrList truthInit = {1, 0, NULL}; size_t used = 0; size_t allocated = 0; char intStr[255]; const int DATA_SIZE = (sizeof(DATA) / sizeof(char *)) - 1; + StrList *testfile_list = NULL; + char testfile[PATH_MAX]; + char *testfile_data; // Initialize string list and check initial state strList = strlist_init(); @@ -101,13 +108,13 @@ int main(int argc, char *argv[]) { myassert(strListCopy != NULL, "strlist_copy failed\n"); // Now compare the arrays to make sure they're identical - myassert(strlist_cmp(strList, strListCopy) == 0, "strlist_copy result does not match original StrList contents"); + myassert(strlist_cmp(strList, strListCopy) == 0, "strlist_copy result does not match original StrList contents\n"); // Sort the array to see if it works. strlist_sort(strListCopy, SPM_SORT_LEN_ASCENDING); // The array just got modified, so check to make sure they are NOT identical - myassert(strlist_cmp(strList, strListCopy) == 1, "StrList data matches original StrList contents (after modification)"); + myassert(strlist_cmp(strList, strListCopy) == 1, "StrList data matches original StrList contents (after modification)\n"); story = join(strListCopy->data, " "); myassert(strcmp(story, story_truth_sort_asc) == 0, storyFmt, story_truth_sort_asc, story); @@ -145,38 +152,63 @@ int main(int argc, char *argv[]) { // NOTE: My focus is on 64-bit, so if you're compiling this on a 32-bit computer // and these tests fail for you... That's a shame. testValue.signed_char = strlist_item_as_char(strList, DATA_SIZE + int8_max); - myassert(testValue.signed_char == INT8_MAX, "int8_max incorrect: %d", testValue.signed_char); + myassert(testValue.signed_char == INT8_MAX, "int8_max incorrect: %d\n", testValue.signed_char); testValue.unsigned_char = strlist_item_as_uchar(strList, DATA_SIZE + uint8_max); - myassert(testValue.unsigned_char == UINT8_MAX, "uint8_max incorrect: %d", testValue.unsigned_char); + myassert(testValue.unsigned_char == UINT8_MAX, "uint8_max incorrect: %d\n", testValue.unsigned_char); testValue.signed_short = strlist_item_as_short(strList, DATA_SIZE + int16_max); - myassert(testValue.signed_short == INT16_MAX, "int16_max incorrect: %d", testValue.signed_short); + myassert(testValue.signed_short == INT16_MAX, "int16_max incorrect: %d\n", testValue.signed_short); testValue.unsigned_short = strlist_item_as_ushort(strList, DATA_SIZE + uint16_max); - myassert(testValue.unsigned_short == UINT16_MAX, "uint16_max incorrect: %d", testValue.unsigned_short); + myassert(testValue.unsigned_short == UINT16_MAX, "uint16_max incorrect: %d\n", testValue.unsigned_short); testValue.signed_int = strlist_item_as_int(strList, DATA_SIZE + int32_max); - myassert(testValue.signed_int == INT32_MAX, "int32_max incorrect: %d", testValue.signed_int); + myassert(testValue.signed_int == INT32_MAX, "int32_max incorrect: %d\n", testValue.signed_int); testValue.unsigned_int = strlist_item_as_uint(strList, DATA_SIZE + uint32_max); - myassert(testValue.unsigned_int == UINT32_MAX, "uint32_max incorrect: %d", testValue.unsigned_int); + myassert(testValue.unsigned_int == UINT32_MAX, "uint32_max incorrect: %d\n", testValue.unsigned_int); testValue.signed_long = strlist_item_as_long(strList, DATA_SIZE + int64_max); - myassert(testValue.signed_long == INT64_MAX, "int64_max (long) incorrect: %ld", testValue.signed_long); + myassert(testValue.signed_long == INT64_MAX, "int64_max (long) incorrect: %ld\n", testValue.signed_long); testValue.unsigned_long = strlist_item_as_ulong(strList, DATA_SIZE + uint64_max); - myassert(testValue.unsigned_long == UINT64_MAX, "uint64_max (long) incorrect: %lu", testValue.unsigned_long); + myassert(testValue.unsigned_long == UINT64_MAX, "uint64_max (long) incorrect: %lu\n", testValue.unsigned_long); testValue.signed_long_long = strlist_item_as_long_long(strList, DATA_SIZE + int64_max); - myassert(testValue.signed_long_long == INT64_MAX, "int64_max (long long) incorrect: %lld", testValue.signed_long_long); + myassert(testValue.signed_long_long == INT64_MAX, "int64_max (long long) incorrect: %lld\n", testValue.signed_long_long); testValue.unsigned_long_long = strlist_item_as_ulong_long(strList, DATA_SIZE + uint64_max); - myassert(testValue.unsigned_long_long == UINT64_MAX, "uint64_max (long long) incorrect: %llu", testValue.unsigned_long_long); + myassert(testValue.unsigned_long_long == UINT64_MAX, "uint64_max (long long) incorrect: %llu\n", testValue.unsigned_long_long); testValue.floating = strlist_item_as_float(strList, DATA_SIZE + uint64_max + 1); - myassert(testValue.floating == MAXFLOAT, "floating point maximum incorrect: %f", testValue.floating); + myassert(testValue.floating == MAXFLOAT, "floating point maximum incorrect: %f\n", testValue.floating); + + // Read a text file into a StrList + testfile_data = join(testfile_truth, "\n"); + testfile_list = strlist_init(); + char *base = strdup(basename(__FILE__)); + sprintf(testfile, "%s.txt", base); + free(base); + + if (exists(testfile)) { + unlink(testfile); + } + + mock(testfile, testfile_data, sizeof(char), strlen(testfile_data)); + strlist_append_file(testfile_list, testfile, NULL); + + myassert(testfile_list != NULL, "testfile_list was not initialized\n"); + size_t testfile_record_count = strlist_count(testfile_list); + + for (size_t record = 0; record < testfile_record_count; record++) { + char *item = strlist_item(testfile_list, record); + char *orig = testfile_truth[record]; + strip(item); + myassert(strcmp(orig, item) == 0, "item is '%s', expected '%s'", item, orig); + } + strlist_free(testfile_list); strlist_free(strList); return 0; }
\ No newline at end of file |