From: Alberto Leiva Popper Date: Tue, 8 Oct 2024 21:11:24 +0000 (-0600) Subject: Remove the path builder X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9e82b1d364789c9b6f6ad2be65c54d9b89d9a8a;p=thirdparty%2FFORT-validator.git Remove the path builder This has become overkill since design 5 and chdir() trivialized cache pathing. --- diff --git a/src/cachetmp.c b/src/cachetmp.c index 856248f4..b9cccc8d 100644 --- a/src/cachetmp.c +++ b/src/cachetmp.c @@ -1,40 +1,31 @@ #include "cachetmp.h" #include +#include +#include "log.h" #include "types/path.h" static atomic_uint file_counter; /* - * Returns a unique temporary file name in the local cache. Note, it's a name, - * and it's pretty much reserved. The file itself will not be created. + * Returns (in @buf, which needs to length CACHE_TMPFILE_BUFLEN) a unique + * temporary file name in the local cache. + * Note, it's a name, and it's pretty much reserved. The file itself will not be + * created. * * The file will not be automatically deleted when it is closed or the program * terminates. - * - * The name of the function is inherited from tmpfile(3). - * - * The resulting string needs to be released. */ -int -cache_tmpfile(char **filename) +void +cache_tmpfile(char *buf) { - struct path_builder pb; - int error; - - pb_init(&pb); - - error = pb_append(&pb, CACHE_TMPDIR); - if (error) - goto fail; - error = pb_append_u32(&pb, atomic_fetch_add(&file_counter, 1u)); - if (error) - goto fail; + unsigned int next; + int written; - *filename = pb.string; - return 0; + next = atomic_fetch_add(&file_counter, 1u); -fail: pb_cleanup(&pb); - return error; + written = snprintf(buf, CACHE_TMPFILE_BUFLEN, CACHE_TMPDIR "/%X", next); + if (written >= CACHE_TMPFILE_BUFLEN) + pr_crit("I ran out of temporal directories: %u", next); } diff --git a/src/cachetmp.h b/src/cachetmp.h index dec35d11..af1c9d0a 100644 --- a/src/cachetmp.h +++ b/src/cachetmp.h @@ -2,7 +2,8 @@ #define SRC_CACHETMP_H_ #define CACHE_TMPDIR "tmp" +#define CACHE_TMPFILE_BUFLEN 24 /* tmp/%X\0 */ -int cache_tmpfile(char **); /* Return new unique path in /tmp/ */ +void cache_tmpfile(char *); /* Return new unique path in /tmp/ */ #endif /* SRC_CACHETMP_H_ */ diff --git a/src/init.c b/src/init.c index 4faf4587..9839152b 100644 --- a/src/init.c +++ b/src/init.c @@ -7,35 +7,20 @@ static int fetch_url(char const *url, char const *filename) { - struct path_builder pb; + char *path; int error; - pb_init(&pb); - error = pb_append(&pb, config_get_tal()); - if (error) - goto pbfail; - error = pb_append(&pb, filename); - if (error) - goto pbfail; - - error = http_download_direct(url, pb.string); - if (error) - goto dlfail; - - fprintf(stdout, "Successfully fetched '%s'!\n\n", pb.string); - pb_cleanup(&pb); - return 0; + path = path_join(config_get_tal(), filename); -pbfail: - fprintf(stderr, "Cannot determine destination path: %s\n", - strerror(abs(error))); - pb_cleanup(&pb); - return error; + error = http_download_direct(url, path); + if (error) { + fprintf(stderr, "Couldn't fetch '%s': %s\n", + path, strerror(abs(error))); + goto end; + } -dlfail: - fprintf(stderr, "Couldn't fetch '%s': %s\n", pb.string, - strerror(abs(error))); - pb_cleanup(&pb); + fprintf(stdout, "Successfully fetched '%s'!\n\n", path); +end: free(path); return error; } diff --git a/src/object/manifest.c b/src/object/manifest.c index 221483d2..6700c123 100644 --- a/src/object/manifest.c +++ b/src/object/manifest.c @@ -12,6 +12,7 @@ #include "object/signed_object.h" #include "thread_var.h" #include "types/path.h" +#include "types/url.h" static int decode_manifest(struct signed_object *sobj, struct Manifest **result) @@ -270,7 +271,7 @@ build_rpp(char const *mft_url, struct Manifest *mft, struct cache_cage *cage, shuffle_mft_files(mft); rpp = &parent->rpp; - rpp_url = path_parent(mft_url); + rpp_url = url_parent(mft_url); // XXX rpp->nfiles = mft->fileList.list.count; rpp->files = pzalloc(rpp->nfiles * sizeof(*rpp->files)); @@ -287,7 +288,7 @@ build_rpp(char const *mft_url, struct Manifest *mft, struct cache_cage *cage, if (error) goto revert; - dst->url = path_childn(rpp_url, + dst->url = path_njoin(rpp_url, (char const *)src->file.buf, src->file.size); diff --git a/src/print_file.c b/src/print_file.c index 1739b739..c978ea64 100644 --- a/src/print_file.c +++ b/src/print_file.c @@ -38,11 +38,10 @@ rsync2bio_tmpdir(char const *src) { #define TMPDIR "/tmp/fort-XXXXXX" - struct path_builder pb; char buf[sizeof(TMPDIR)]; char *tmpdir; + char *tmpfile; BIO *result = NULL; - int error; strcpy(buf, TMPDIR); tmpdir = mkdtemp(buf); @@ -51,17 +50,10 @@ rsync2bio_tmpdir(char const *src) return NULL; } - pb_init(&pb); - error = pb_append(&pb, tmpdir); - if (error) - goto end; - error = pb_append(&pb, path_filename(src)); - if (error) - goto end; - - result = __rsync2bio(src, pb.string); + tmpfile = path_join(tmpdir, path_filename(src)); + result = __rsync2bio(src, tmpfile); + free(tmpfile); -end: pb_cleanup(&pb); return result; } diff --git a/src/rrdp.c b/src/rrdp.c index 6912919f..1fcd6fe5 100644 --- a/src/rrdp.c +++ b/src/rrdp.c @@ -897,41 +897,31 @@ validate_session_desync(struct rrdp_state *old_notif, /* TODO (performance) Stream instead of caching notifs, snapshots & deltas. */ static int -dl_tmp(char const *url, char **path) +dl_tmp(char const *url, char *path) { - int error; - - error = cache_tmpfile(path); - if (error) - return error; - - error = http_download(url, *path, 0, NULL); - if (error) - free(*path); - - return error; + cache_tmpfile(path); + return http_download(url, path, 0, NULL); } static int handle_snapshot(struct update_notification *new, struct rrdp_state *state) { - char *tmppath; + char tmppath[CACHE_TMPFILE_BUFLEN]; int error; pr_val_debug("Processing snapshot."); fnstack_push(new->snapshot.uri); - error = dl_tmp(new->snapshot.uri, &tmppath); + error = dl_tmp(new->snapshot.uri, tmppath); if (error) - goto end1; + goto end; error = validate_hash(&new->snapshot, tmppath); if (error) - goto end2; + goto end; error = parse_snapshot(&new->session, tmppath, state); // delete_file(tmppath); XXX -end2: free(tmppath); -end1: fnstack_pop(); +end: fnstack_pop(); return error; } @@ -988,19 +978,18 @@ static int handle_delta(struct update_notification *notif, struct notification_delta *delta, struct rrdp_state *state) { - char *tmppath; + char tmppath[CACHE_TMPFILE_BUFLEN]; int error; pr_val_debug("Processing delta '%s'.", delta->meta.uri); fnstack_push(delta->meta.uri); - error = dl_tmp(delta->meta.uri, &tmppath); + error = dl_tmp(delta->meta.uri, tmppath); if (error) goto end; error = parse_delta(notif, delta, tmppath, state); // delete_file(tmppath); XXX - free(tmppath); end: fnstack_pop(); return error; } @@ -1148,25 +1137,23 @@ static int dl_notif(struct cache_mapping const *map, time_t mtim, bool *changed, struct update_notification *new) { - char *tmppath; + char tmppath[CACHE_TMPFILE_BUFLEN]; int error; - error = cache_tmpfile(&tmppath); - if (error) - return error; + cache_tmpfile(tmppath); *changed = false; error = http_download(map->url, tmppath, mtim, changed); if (error) - goto end; + return error; if (!(*changed)) { pr_val_debug("The Notification has not changed."); - goto end; + return 0; } error = parse_notification(map->url, tmppath, new); if (error) - goto end; + return error; if (remove(tmppath) < 0) { pr_val_warn("Can't remove notification's temporal file: %s", @@ -1175,8 +1162,7 @@ dl_notif(struct cache_mapping const *map, time_t mtim, bool *changed, /* Nonfatal; fall through */ } -end: free(tmppath); - return error; + return 0; } /* diff --git a/src/types/path.c b/src/types/path.c index 2a17a170..d793ab32 100644 --- a/src/types/path.c +++ b/src/types/path.c @@ -39,184 +39,6 @@ token_next(struct tokenizer *tkn) return true; } -/* @reserve needs to be < INITIAL_CAPACITY. */ -void -__pb_init(struct path_builder *pb, size_t reserve) -{ - pb->string = pmalloc(INITIAL_CAPACITY); - pb->string[reserve] = 0; - pb->len = reserve; - pb->capacity = INITIAL_CAPACITY; -} - -static int -pb_grow(struct path_builder *pb, size_t total_len, char const *addend) -{ - if (total_len > MAX_CAPACITY) { - pr_val_err("Unable to concatenate '%.32s' (might be truncated) to path '%s': Path too long (%zu > %u)", - addend, pb->string, total_len, MAX_CAPACITY); - return ENOSPC; - } - - do { - pb->capacity *= 2; - } while (total_len > pb->capacity); - - pb->string = prealloc(pb->string, pb->capacity); - return 0; -} - -int -pb_appendn(struct path_builder *pb, char const *addend, size_t addlen) -{ - size_t total_len; - bool add_slash; - int error; - - if (addlen == 0) - return 0; - - add_slash = (pb->len != 0); - if (add_slash) - addlen++; - - total_len = pb->len + addlen + 1; - if (total_len > pb->capacity) { - error = pb_grow(pb, total_len, addend); - if (error) - return error; - } - - if (add_slash) { - pb->string[pb->len] = '/'; - memcpy(pb->string + pb->len + 1, addend, addlen); - } else { - memcpy(pb->string + pb->len, addend, addlen); - } - - pb->len += addlen; - pb->string[pb->len] = 0; - - return 0; -} - -int -pb_append(struct path_builder *pb, char const *addend) -{ - return (addend != NULL) ? pb_appendn(pb, addend, strlen(addend)) : 0; -} - -int -pb_append_u32(struct path_builder *pb, uint32_t num) -{ -#define MAX_STRLEN 9 /* 8 hexadecimal digits plus null chara */ - char buffer[MAX_STRLEN]; - int num_len; - - num_len = snprintf(buffer, MAX_STRLEN, "%X", num); - if (num_len < 0) { - pr_val_err("Cannot stringify number '%u': Unknown cause. Error code might be %d.", - num, num_len); - return EIO; /* num_len is not necessarily an error code */ - } - if (num_len >= MAX_STRLEN) - pr_crit("pb: Number %u requires %d digits", num, num_len); - - return pb_appendn(pb, buffer, num_len); -} - -/* Removes the last component added. */ -int -pb_pop(struct path_builder *pb, bool fatal) -{ - size_t i; - - if (pb->len == 0 || (pb->len == 1 && pb->string[0] == '/')) { - if (fatal) - pr_crit("Programming error: Attempting to pop empty path builder"); - return -pr_val_err("Path cannot '..' over the root."); - } - - for (i = pb->len - 1; i >= 1; i--) { - if (pb->string[i] == '/') { - pb->string[i] = 0; - pb->len = i; - return 0; - } - } - - if (pb->string[0] == '/') { - pb->string[1] = 0; - pb->len = 1; - } else { - pb->string[0] = 0; - pb->len = 0; - } - return 0; -} - -static void -reverse_string(char *str, size_t len) -{ - char *b, *e; /* beginning, end */ - char tmp; - - for (b = str, e = str + len - 1; b < e; b++, e--) { - tmp = *b; - *b = *e; - *e = tmp; - } -} - -/* Turns ab/cd/ef/gh into gh/ef/cd/ab. */ -void -pb_reverse(struct path_builder *pb) -{ - size_t min; - size_t max; - - reverse_string(pb->string, pb->len); - - min = 0; - for (max = 1; max < pb->len; max++) { - if (pb->string[max] == '/') { - reverse_string(&pb->string[min], max - min); - max++; - min = max; - } - } - reverse_string(&pb->string[min], pb->len - min); -} - -void -pb_cleanup(struct path_builder *pb) -{ - free(pb->string); -} - -/* Note, fatal is hardcoded as 1. */ -char * -path_parent(char const *child) -{ - struct path_builder pb; - pb.string = pstrdup(child); - pb.len = pb.capacity = strlen(pb.string); - pb_pop(&pb, true); - return pb.string; -} - -char * -path_childn(char const *p1, char const *p2, size_t p2len) -{ - struct path_builder pb; - - pb_init(&pb); - pb_append(&pb, p1); // XXX - pb_appendn(&pb, p2, p2len); // XXX - - return pb.string; -} - char const * path_filename(char const *path) { @@ -227,27 +49,34 @@ path_filename(char const *path) /* * Cannot return NULL. * - * XXX I'm starting to use this more. Probably clean the slashes. + * XXX I'm starting to use this more. Probably sanitize better. */ char * path_join(char const *path1, char const *path2) { - size_t n; - char *result; - int written; - // XXX needed? if (path1[0] == 0) return pstrdup(path2); if (path2 == NULL || path2[0] == 0) return pstrdup(path1); - n = strlen(path1) + strlen(path2) + 2; + return path_njoin(path1, path2, strlen(path2)); +} + +char * +path_njoin(char const *p1, char const *p2, size_t p2len) +{ + size_t n; + char *result; + int written; + + n = strlen(p1) + p2len + 2; result = pmalloc(n); - written = snprintf(result, n, "%s/%s", path1, path2); + written = snprintf(result, n, "%s/%.*s", p1, (int) p2len, p2); if (written != n - 1) - pr_crit("join_paths: %zu %d %s %s", n, written, path1, path2); + pr_crit("path_njoin: %zu %d %s %.*s", + n, written, p1, (int) p2len, p2); return result; } diff --git a/src/types/path.h b/src/types/path.h index 84bcdd09..ec31211e 100644 --- a/src/types/path.h +++ b/src/types/path.h @@ -1,18 +1,8 @@ #ifndef SRC_TYPES_PATH_H_ #define SRC_TYPES_PATH_H_ -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include // XXX rename struct tokenizer { @@ -23,33 +13,8 @@ struct tokenizer { void token_init(struct tokenizer *, char const *); bool token_next(struct tokenizer *tkn); -struct path_builder { - char *string; - size_t len; /* Includes the null chara */ - size_t capacity; -}; - -void __pb_init(struct path_builder *, size_t); -#define pb_init(pb) __pb_init(pb, 0) - -/* - * The appends are atomic. - * They are also naive; they don't collapse `.`, `..` nor slashes. - */ - -int pb_appendn(struct path_builder *, char const *, size_t); -int pb_append(struct path_builder *, char const *); -int pb_append_u32(struct path_builder *, uint32_t); - -int pb_pop(struct path_builder *, bool); - -void pb_reverse(struct path_builder *); - -void pb_cleanup(struct path_builder *); - -char *path_parent(char const *); -char *path_childn(char const *, char const *, size_t); char const *path_filename(char const *); char *path_join(char const *, char const *); +char *path_njoin(char const *, char const *, size_t); #endif /* SRC_TYPES_PATH_H_ */ diff --git a/src/types/url.c b/src/types/url.c index 46c4dffc..bfc5a720 100644 --- a/src/types/url.c +++ b/src/types/url.c @@ -133,6 +133,13 @@ fail: free(normal); return NULL; } +char * +url_parent(char const *child) +{ + char *slash = strrchr(child, '/'); + return (slash != NULL) ? pstrndup(child, slash - child) : NULL; +} + bool url_same_origin(char const *url1, char const *url2) { diff --git a/src/types/url.h b/src/types/url.h index a2b0ea5d..86c93feb 100644 --- a/src/types/url.h +++ b/src/types/url.h @@ -9,6 +9,7 @@ bool url_is_rsync(char const *); bool url_is_https(char const *); char *url_normalize(char const *); +char *url_parent(char const *); bool url_same_origin(char const *, char const *); #endif /* SRC_TYPES_URL_H_ */ diff --git a/test/Makefile.am b/test/Makefile.am index afb38338..11a8e446 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -29,7 +29,6 @@ check_PROGRAMS += db_table.test check_PROGRAMS += deltas_array.test check_PROGRAMS += hash.test check_PROGRAMS += mft.test -check_PROGRAMS += path.test check_PROGRAMS += pdu_handler.test check_PROGRAMS += pdu_stream.test check_PROGRAMS += rrdp.test @@ -71,9 +70,6 @@ hash_test_LDADD = ${MY_LDADD} mft_test_SOURCES = object/manifest_test.c mft_test_LDADD = ${MY_LDADD} -path_test_SOURCES = types/path_test.c -path_test_LDADD = ${MY_LDADD} - pdu_handler_test_SOURCES = rtr/pdu_handler_test.c pdu_handler_test_LDADD = ${MY_LDADD} ${JANSSON_LIBS} diff --git a/test/types/path_test.c b/test/types/path_test.c deleted file mode 100644 index f56e4626..00000000 --- a/test/types/path_test.c +++ /dev/null @@ -1,334 +0,0 @@ -#include -#include - -#define INITIAL_CAPACITY 8 - -#include "alloc.c" -#include "mock.c" -#include "types/path.c" - -#define CHECK_PB(_string, _capacity) \ - ck_assert_str_eq(_string, pb.string); \ - ck_assert_uint_eq(strlen(_string), pb.len); \ - ck_assert_uint_eq(_capacity, pb.capacity); - -START_TEST(test_append) -{ - struct path_builder pb; - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "")); - CHECK_PB("", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - CHECK_PB("a", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "/a")); - CHECK_PB("/a", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - CHECK_PB("a", 8); - ck_assert_int_eq(0, pb_append(&pb, "b")); - CHECK_PB("a/b", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a/b")); - CHECK_PB("a/b", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a/")); - CHECK_PB("a/", 8); - ck_assert_int_eq(0, pb_append(&pb, "b/")); - CHECK_PB("a//b/", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a/")); - CHECK_PB("a/", 8); - ck_assert_int_eq(0, pb_append(&pb, "b")); - CHECK_PB("a//b", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - CHECK_PB("a", 8); - ck_assert_int_eq(0, pb_append(&pb, "/b")); - CHECK_PB("a//b", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a/")); - CHECK_PB("a/", 8); - ck_assert_int_eq(0, pb_append(&pb, "/b")); - CHECK_PB("a///b", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "//a")); - CHECK_PB("//a", 8); - ck_assert_int_eq(0, pb_append(&pb, "///")); - CHECK_PB("//a////", 8); - ck_assert_int_eq(0, pb_append(&pb, "b////")); - CHECK_PB("//a/////b////", 16); - ck_assert_int_eq(0, pb_append(&pb, "/////c//////")); - CHECK_PB("//a/////b//////////c//////", 32); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "//a///b//c//")); - CHECK_PB("//a///b//c//", 16); - pb_cleanup(&pb); -} -END_TEST - -/* Actually mainly designed to manhandle capacity expansion */ -START_TEST(test_uint) -{ - struct path_builder pb; - - pb_init(&pb); - pb_append_u32(&pb, 0x123); - CHECK_PB("123", 8); - pb_cleanup(&pb); - - pb_init(&pb); - pb_append_u32(&pb, 0x1234567); - CHECK_PB("1234567", 8); - pb_cleanup(&pb); - - pb_init(&pb); - pb_append_u32(&pb, 0x12345678); - CHECK_PB("12345678", 16); - pb_cleanup(&pb); - - pb_init(&pb); - pb_append_u32(&pb, 0x12345); - CHECK_PB("12345", 8); - pb_append_u32(&pb, 0x7); - CHECK_PB("12345/7", 8); - pb_cleanup(&pb); - - pb_init(&pb); - pb_append_u32(&pb, 0x12345); - CHECK_PB("12345", 8); - pb_append_u32(&pb, 0x78); - CHECK_PB("12345/78", 16); - pb_cleanup(&pb); - - pb_init(&pb); - pb_append_u32(&pb, 0x12345); - CHECK_PB("12345", 8); - pb_append_u32(&pb, 0x789); - CHECK_PB("12345/789", 16); - pb_cleanup(&pb); -} -END_TEST - -START_TEST(test_pop) -{ - struct path_builder pb; - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - CHECK_PB("a", 8); - ck_assert_int_eq(0, pb_append(&pb, "b")); - CHECK_PB("a/b", 8); - ck_assert_int_eq(0, pb_pop(&pb, false)); - CHECK_PB("a", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "abc")); - CHECK_PB("abc", 8); - ck_assert_int_eq(0, pb_append(&pb, "def")); - CHECK_PB("abc/def", 8); - ck_assert_int_eq(0, pb_pop(&pb, false)); - CHECK_PB("abc", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - CHECK_PB("a", 8); - ck_assert_int_eq(0, pb_pop(&pb, false)); - CHECK_PB("", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "/a")); - CHECK_PB("/a", 8); - ck_assert_int_eq(0, pb_pop(&pb, false)); - CHECK_PB("/", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(EINVAL, pb_pop(&pb, false)); - CHECK_PB("", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - ck_assert_int_eq(0, pb_pop(&pb, false)); - CHECK_PB("", 8); - ck_assert_int_eq(EINVAL, pb_pop(&pb, false)); - CHECK_PB("", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "/")); - CHECK_PB("/", 8); - ck_assert_int_eq(EINVAL, pb_pop(&pb, false)); - CHECK_PB("/", 8); - pb_cleanup(&pb); -} -END_TEST - -START_TEST(test_reverse) -{ - struct path_builder pb; - - /* 0 components */ - pb_init(&pb); - pb_reverse(&pb); - CHECK_PB("", 8); - pb_cleanup(&pb); - - /* 1 component */ - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - pb_reverse(&pb); - CHECK_PB("a", 8); - pb_cleanup(&pb); - - /* 2 components */ - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - ck_assert_int_eq(0, pb_append(&pb, "b")); - pb_reverse(&pb); - CHECK_PB("b/a", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "abc")); - ck_assert_int_eq(0, pb_append(&pb, "def")); - pb_reverse(&pb); - CHECK_PB("def/abc", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "abcd")); - ck_assert_int_eq(0, pb_append(&pb, "efgh")); - pb_reverse(&pb); - CHECK_PB("efgh/abcd", 16); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "abc")); - ck_assert_int_eq(0, pb_append(&pb, "efgh")); - pb_reverse(&pb); - CHECK_PB("efgh/abc", 16); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "abcd")); - ck_assert_int_eq(0, pb_append(&pb, "fgh")); - pb_reverse(&pb); - CHECK_PB("fgh/abcd", 16); - pb_cleanup(&pb); - - /* 3 components */ - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "abc")); - ck_assert_int_eq(0, pb_append(&pb, "def")); - ck_assert_int_eq(0, pb_append(&pb, "ghi")); - pb_reverse(&pb); - CHECK_PB("ghi/def/abc", 16); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "ab")); - ck_assert_int_eq(0, pb_append(&pb, "cde")); - ck_assert_int_eq(0, pb_append(&pb, "fghi")); - pb_reverse(&pb); - CHECK_PB("fghi/cde/ab", 16); - pb_cleanup(&pb); - - /* 4 components */ - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - ck_assert_int_eq(0, pb_append(&pb, "b")); - ck_assert_int_eq(0, pb_append(&pb, "c")); - ck_assert_int_eq(0, pb_append(&pb, "d")); - pb_reverse(&pb); - CHECK_PB("d/c/b/a", 8); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "ab")); - ck_assert_int_eq(0, pb_append(&pb, "cd")); - ck_assert_int_eq(0, pb_append(&pb, "ef")); - ck_assert_int_eq(0, pb_append(&pb, "gh")); - pb_reverse(&pb); - CHECK_PB("gh/ef/cd/ab", 16); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "a")); - ck_assert_int_eq(0, pb_append(&pb, "bcd")); - ck_assert_int_eq(0, pb_append(&pb, "efgh")); - ck_assert_int_eq(0, pb_append(&pb, "ijklm")); - pb_reverse(&pb); - CHECK_PB("ijklm/efgh/bcd/a", 32); - pb_cleanup(&pb); - - pb_init(&pb); - ck_assert_int_eq(0, pb_append(&pb, "abcdefghijklmnopq")); - ck_assert_int_eq(0, pb_append(&pb, "r")); - ck_assert_int_eq(0, pb_append(&pb, "stu")); - ck_assert_int_eq(0, pb_append(&pb, "vx")); - pb_reverse(&pb); - CHECK_PB("vx/stu/r/abcdefghijklmnopq", 32); - pb_cleanup(&pb); -} -END_TEST - -static Suite * -create_suite(void) -{ - Suite *suite; - TCase *core; - - core = tcase_create("functions"); - tcase_add_test(core, test_append); - tcase_add_test(core, test_uint); - tcase_add_test(core, test_pop); - tcase_add_test(core, test_reverse); - - suite = suite_create("path_builder"); - suite_add_tcase(suite, core); - return suite; -} - -int -main(int argc, char **argv) -{ - Suite *suite; - SRunner *runner; - int tests_failed; - - suite = create_suite(); - - runner = srunner_create(suite); - srunner_run_all(runner, CK_NORMAL); - tests_failed = srunner_ntests_failed(runner); - srunner_free(runner); - - return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -}