]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Friday
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Sat, 13 Jul 2024 00:43:06 +0000 (18:43 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Sat, 13 Jul 2024 00:43:06 +0000 (18:43 -0600)
14 files changed:
src/cache/cachent.c
src/cache/cachent.h
src/cache/local_cache.c
src/common.c
src/common.h
src/file.c
src/http/http.c
src/rrdp.c
src/rsync/rsync.c
src/types/url.c
test/cache/cachent_test.c
test/cache/local_cache_test.c
test/mock.c
test/types/url_test.c

index 36a0acfecb825fef38fb976351662ec1e2e351a1..485ee8e73f3f96b76a7392af24d05b0553159c3d 100644 (file)
@@ -6,7 +6,6 @@
 #include "data_structure/path_builder.h"
 #include "types/url.h"
 
-/* @schema must contain a colon suffix, otherwise lookups won't work */
 struct cache_node *
 cachent_create_root(char const *schema)
 {
@@ -80,6 +79,45 @@ end: pb_cleanup(&pb);
        return error;
 }
 
+static struct cache_node *
+find_child(struct cache_node *parent, char const *name, size_t namelen)
+{
+       struct cache_node *child;
+       HASH_FIND(hh, parent->children, name, namelen, child);
+       return child;
+}
+
+/*
+ * Returns perfect match or NULL. @msm will point to the Most Specific Match.
+ * Assumes @path is normalized.
+ * XXX if root doesn't match path, will return garbage
+ */
+struct cache_node *
+cachent_find(struct cache_node *root, char const *path, struct cache_node **msm)
+{
+       struct tokenizer tkn;
+       struct cache_node *parent;
+       struct cache_node *child;
+
+       token_init(&tkn, path);
+
+       if (!token_next(&tkn) || strncmp(root->name, tkn.str, tkn.len) != 0) {
+               *msm = NULL;
+               return NULL;
+       }
+
+       for (parent = child = root; token_next(&tkn); parent = child) {
+               child = find_child(parent, tkn.str, tkn.len);
+               if (!child) {
+                       *msm = parent;
+                       return NULL;
+               }
+       }
+
+       *msm = parent;
+       return child;
+}
+
 /* Get or create parent's child. */
 static struct cache_node *
 provide(struct cache_node *parent, char const *url,
@@ -87,15 +125,17 @@ provide(struct cache_node *parent, char const *url,
 {
        struct cache_node *child;
 
-       HASH_FIND(hh, parent->children, name, namelen, child);
+       child = find_child(parent, name, namelen);
        if (child != NULL)
                return child;
 
        child = pzalloc(sizeof(struct cache_node));
        child->url = pstrndup(url, name - url + namelen);
        child->name = child->url + (name - url);
-       if (parent->flags & RSYNC_INHERIT)
+       if ((parent->flags & RSYNC_INHERIT) == RSYNC_INHERIT) {
+               PR_DEBUG_MSG("parent %s has inherit; setting on %s.", parent->name, child->name);
                child->flags = RSYNC_INHERIT;
+       }
        child->parent = parent;
        HASH_ADD_KEYPTR(hh, parent->children, child->name, namelen, child);
        return child;
@@ -213,5 +253,6 @@ print_node(struct cache_node *node, unsigned int tabs)
 void
 cachent_print(struct cache_node *node)
 {
-       print_node(node, 0);
+       if (node)
+               print_node(node, 0);
 }
index 7443b7932882dcce2b672fdc1a648ab106cd5527..1d124caa77f496170113e927c5769709786f179b 100644 (file)
@@ -47,7 +47,7 @@
 // XXX rename to cache_entity or cachent
 struct cache_node {
        char const *name;       /* Points to the last component of @url XXX redundant */
-       char *url;
+       char *url;              /* Normalized */
        int flags;
 
        int dlerr;              /* Result code of recent download attempt */
@@ -77,6 +77,8 @@ struct cache_node *cachent_create_root(char const *);
 int cachent_traverse(struct cache_node *,
     bool (*cb)(struct cache_node *, char const *));
 
+struct cache_node *cachent_find(struct cache_node *, char const *,
+    struct cache_node **);
 struct cache_node *cachent_provide(struct cache_node *, char const *);
 void cachent_delete(struct cache_node *);
 
index 2b0d64471c79e98cf908dc8aa05c7b441c96a673..b6a4d338e79b96313063833b623fca42ed4b5e2c 100644 (file)
@@ -337,8 +337,8 @@ cache_tmpfile(char **filename)
 static void
 load_tal_json(void)
 {
-       cache.rsync = cachent_create_root("rsync:");
-       cache.https = cachent_create_root("https:");
+       cache.rsync = cachent_create_root("rsync");
+       cache.https = cachent_create_root("https");
 
 //     char *filename;
 //     json_t *root;
@@ -481,37 +481,6 @@ write_tal_json(void)
 //     free(filename);
 }
 
-/*
- * Returns perfect match or NULL. @msm will point to the Most Specific Match.
- * Always consumes @path.
- */
-static struct cache_node *
-find_msm(struct cache_node *root, char *path, struct cache_node **msm)
-{
-       struct cache_node *node, *child;
-       char *nm, *sp; /* name, saveptr */
-       size_t keylen;
-
-       *msm = NULL;
-       node = root;
-       nm = strtok_r(path + RPKI_SCHEMA_LEN, "/", &sp); // XXX
-
-       for (; nm; nm = strtok_r(NULL, "/", &sp)) {
-               keylen = strlen(nm);
-               HASH_FIND(hh, node->children, nm, keylen, child);
-               if (child == NULL) {
-                       free(path);
-                       *msm = node;
-                       return NULL;
-               }
-               node = child;
-       }
-
-       free(path);
-       *msm = node;
-       return node;
-}
-
 /*
  * The "rsync module" is the component immediately after the domain.
  *
@@ -620,10 +589,13 @@ try_uri(char const *uri, int (*download)(struct cache_node *),
                return pr_val_err("Malformed URL: %s", uri);
 
        if (download != NULL) {
+               PR_DEBUG;
                if (rpp->flags & CNF_FRESH) {
+                       PR_DEBUG_MSG("%s is fresh.", rpp->url);
                        if (rpp->dlerr)
                                return rpp->dlerr;
                } else {
+                       PR_DEBUG;
                        rpp->flags |= CNF_FRESH;
                        error = rpp->dlerr = download(rpp);
                        if (error)
@@ -700,17 +672,22 @@ cache_print(void)
 static bool
 commit_rpp_delta(struct cache_node *node, char const *path)
 {
+       int error;
+
        PR_DEBUG_MSG("Commiting %s", node->url);
 
        if (node->tmpdir == NULL)
                return true; /* Not updated */
 
-       if (node->flags & CNF_VALID)
-               rename(node->tmpdir, path); // XXX
-       else
+       if (node->flags & CNF_VALID) {
+               error = file_merge_into(node->tmpdir, path);
+               if (error)
+                       printf("rename errno: %d\n", error); // XXX
+       } else {
                /* XXX same; just do remove(). */
                /* XXX and rename "tmpdir" into "tmp". */
                file_rm_f(node->tmpdir);
+       }
 
        free(node->tmpdir);
        node->tmpdir = NULL;
@@ -772,27 +749,24 @@ get_days_ago(int days)
        return last_week;
 }
 
-//static void
-//cleanup_tmp(struct rpki_cache *cache, struct cache_node *node)
-//{
-//     enum map_type type;
-//     char const *path;
-//     int error;
-//
-//     type = map_get_type(node->map);
-//     if (type != MAP_NOTIF && type != MAP_TMP)
-//             return;
-//
-//     path = map_get_path(node->map);
-//     pr_op_debug("Deleting temporal file '%s'.", path);
-//     error = file_rm_f(path);
-//     if (error)
-//             pr_op_err("Could not delete '%s': %s", path, strerror(error));
-//
-//     if (type != MAP_NOTIF)
-//             delete_node(cache, node);
-//}
-//
+static int
+rmf(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
+{
+       if (remove(fpath))
+               pr_op_warn("Can't remove %s: %s", fpath, strerror(errno));
+       return 0;
+}
+
+static void
+cleanup_tmp(void)
+{
+       char *tmpdir = get_cache_filename(TMPDIR, true);
+       if (nftw(tmpdir, rmf, 32, FTW_DEPTH | FTW_PHYS))
+               pr_op_warn("Cannot empty the cache's tmp directory: %s",
+                   strerror(errno));
+       free(tmpdir);
+}
+
 //static void
 //cleanup_node(struct rpki_cache *cache, struct cache_node *node,
 //    time_t last_week)
@@ -867,45 +841,72 @@ static int
 nftw_remove_abandoned(const char *path, const struct stat *st,
     int typeflag, struct FTW *ftw)
 {
+       char const *lookup;
        struct cache_node *pm; /* Perfect Match */
        struct cache_node *msm; /* Most Specific Match */
        struct timespec now;
 
-       PR_DEBUG_MSG("Removing potentially abandoned %s", path);
+       // XXX
+       lookup = path + strlen(config_get_local_repository());
+       while (lookup[0] == '/')
+               lookup++;
+       PR_DEBUG_MSG("Removing if abandoned: %s", lookup);
 
-       /* XXX node->parent has to be set */
-       pm = find_msm(nftw_root, pstrdup(path), &msm);
-       if (!pm && !(msm->flags & CNF_RSYNC))
+       pm = cachent_find(nftw_root, lookup, &msm);
+       if (pm == cache.rsync || pm == cache.https) {
+               PR_DEBUG_MSG("%s", "Root; skipping.");
+               return 0;
+       }
+       if (!msm) {
+               PR_DEBUG_MSG("%s", "Not matched by the tree.");
+               goto unknown;
+       }
+       if (!pm && !(msm->flags & CNF_RSYNC)) {
+               PR_DEBUG_MSG("%s", "Unknown.");
                goto unknown; /* The traversal is depth-first */
+       }
 
        if (S_ISDIR(st->st_mode)) {
                /*
                 * rmdir() fails if the directory is not empty.
                 * This will happen most of the time.
                 */
-               if (rmdir(path) == 0)
+               if (rmdir(path) == 0) {
+                       PR_DEBUG_MSG("%s", "Directory deleted; purging node.");
                        cachent_delete(pm);
-               else if (errno == ENOENT)
+               } else if (errno == ENOENT) {
+                       PR_DEBUG_MSG("%s", "Directory does not exist; purging node.");
                        cachent_delete(pm);
+               } else {
+                       PR_DEBUG_MSG("%s", "Directory exists and has contents; skipping.");
+               }
 
        } else if (S_ISREG(st->st_mode)) {
-               if (pm->flags & (CNF_RSYNC | CNF_WITHDRAWN)) {
+               if ((msm->flags & CNF_RSYNC) || !pm || (pm->flags & CNF_WITHDRAWN)) {
                        clock_gettime(CLOCK_REALTIME, &now); // XXX
-                       if (now.tv_sec - st->st_atim.tv_sec > cfg_cache_threshold())
+                       PR_DEBUG_MSG("%ld > %ld", now.tv_sec - st->st_atim.tv_sec, cfg_cache_threshold());
+                       if (now.tv_sec - st->st_atim.tv_sec > cfg_cache_threshold()) {
+                               PR_DEBUG_MSG("%s", "Too old.");
                                goto abandoned;
+                       }
+                       PR_DEBUG_MSG("%s", "Young; preserving.");
                }
 
        } else {
+               PR_DEBUG_MSG("%s", "Unknown type.");
                goto abandoned;
        }
 
        return 0;
 
 abandoned:
+       PR_DEBUG;
        if (pm)
                cachent_delete(pm);
 unknown:
-       remove(path); // XXX
+       PR_DEBUG;
+       if (remove(path))
+               PR_DEBUG_MSG("remove(): %s", strerror(errno)); // XXX
        return 0;
 }
 
@@ -922,11 +923,13 @@ remove_abandoned(void)
        rootpath = join_paths(config_get_local_repository(), "rsync");
 
        nftw_root = cache.rsync;
+       PR_DEBUG_MSG("nftw(%s)", rootpath);
        nftw(rootpath, nftw_remove_abandoned, 32, FTW_DEPTH | FTW_PHYS); // XXX
 
        strcpy(rootpath + strlen(rootpath) - 5, "https");
 
        nftw_root = cache.https;
+       PR_DEBUG_MSG("nftw(%s)", rootpath);
        nftw(rootpath, nftw_remove_abandoned, 32, FTW_DEPTH | FTW_PHYS); // XXX
 
        free(rootpath);
@@ -938,16 +941,12 @@ remove_abandoned(void)
 static void
 cleanup_cache(void)
 {
-//     struct cache_node *node, *tmp;
-//     time_t last_week;
-
        pr_op_debug("Committing successful RPPs.");
        cachent_traverse(cache.rsync, commit_rpp_delta);
        cachent_traverse(cache.https, commit_rpp_delta);
 
-//     pr_op_debug("Cleaning up temporal files.");
-//     HASH_ITER(hh, cache->ht, node, tmp)
-//             cleanup_tmp(cache, node);
+       pr_op_debug("Cleaning up temporal files.");
+       cleanup_tmp();
 
        pr_op_debug("Cleaning up old abandoned and unknown cache files.");
        remove_abandoned();
index 4db2093b003bbc0115798d1f04b3b0e3b914f0d9..d5f9ec25b992caefdbb201bbeb0b2a8f1566e2ea 100644 (file)
@@ -266,11 +266,11 @@ dir_exists(char const *path)
 }
 
 static int
-ensure_dir(char const *path)
+ensure_dir(char const *path, mode_t mode)
 {
        int error;
 
-       if (mkdir(path, 0777) != 0) {
+       if (mkdir(path, mode) != 0) {
                error = errno;
                if (error != EEXIST) {
                        pr_op_err_st("Error while making directory '%s': %s",
@@ -285,7 +285,7 @@ ensure_dir(char const *path)
 /* mkdir -p $_path */
 /* XXX Maybe also short-circuit by parent? */
 int
-mkdir_p(char const *_path, bool include_basename)
+mkdir_p(char const *_path, bool include_basename, mode_t mode)
 {
        char *path, *last_slash;
        int i, result = 0;
@@ -310,13 +310,13 @@ mkdir_p(char const *_path, bool include_basename)
        for (i = 1; path[i] != '\0'; i++) {
                if (path[i] == '/') {
                        path[i] = '\0';
-                       result = ensure_dir(path);
+                       result = ensure_dir(path, mode);
                        path[i] = '/';
                        if (result != 0)
                                goto end; /* error msg already printed */
                }
        }
-       result = ensure_dir(path);
+       result = ensure_dir(path, mode);
 
 end:
        free(path);
index 34333dcf3d52736aec4a963802f1dc1065cd92a2..37154f0a3ae819b48697b7a58b552b7434be3204 100644 (file)
@@ -51,7 +51,7 @@ int foreach_file(char const *, char const *, bool, foreach_file_cb, void *);
 // XXX
 bool valid_file_or_dir(char const *, bool);
 
-int mkdir_p(char const *, bool);
+int mkdir_p(char const *, bool, mode_t);
 int delete_dir_recursive_bottom_up(char const *);
 
 int get_current_time(time_t *);
index 0f83e457b9429ed57547f96d7e6b4429c1d2cebf..bd27d4feb52b336ed5f04329feaf6d01354814cf 100644 (file)
@@ -136,6 +136,60 @@ file_exists(char const *path)
        return (stat(path, &meta) == 0) ? 0 : errno;
 }
 
+/* strlen("cache/tmp/123"), ie. 13 */
+static size_t src_offset;
+/* cache/rsync/a.b.c/d/e */
+static char const *merge_dst;
+
+/* Moves cache/tmp/123/z into cache/rsync/a.b.c/d/e/z. */
+static int
+merge_into(const char *src, const struct stat *st, int typeflag,
+    struct FTW *ftw)
+{
+       char *dst;
+       struct timespec times[2];
+
+       dst = join_paths(merge_dst, &src[src_offset]);
+
+       if (S_ISDIR(st->st_mode)) {
+               PR_DEBUG_MSG("mkdir -p %s", dst);
+               if (mkdir_p(dst, true, st->st_mode)) {
+                       PR_DEBUG_MSG("Failed: %s", strerror(errno));
+                       goto end;
+               }
+
+               times[0] = st->st_atim;
+               times[1] = st->st_mtim;
+               if (utimensat(AT_FDCWD, dst, times, AT_SYMLINK_NOFOLLOW))
+                       PR_DEBUG_MSG("utimensat: %s", strerror(errno));
+       } else {
+               PR_DEBUG_MSG("rename: %s -> %s", src, dst);
+               if (rename(src, dst))
+                       PR_DEBUG_MSG("rename: %s", strerror(errno));
+       }
+
+end:   free(dst);
+       return 0;
+}
+
+/*
+ * Move all the files contained in @src to @dst, overwriting when necessary,
+ * not touching files that exist in @dst but not in @src.
+ *
+ * Both directories have to already exist.
+ *
+ * @src: cache/tmp/123
+ * @dst: cache/rsync/a.b.c/d/e
+ */
+int
+file_merge_into(char const *src, char const *dst)
+{
+       src_offset = strlen(src);
+       merge_dst = dst;
+       /* TODO (performance) optimize that 32 */
+       return nftw(src, merge_into, 32, FTW_PHYS);
+}
+
 /*
  * Like remove(), but don't care if the file is already deleted.
  */
index 86b0eb58914caf59508452fe4d7008f0222ca5af..3e67596e73808e432033e6f52148567ea8ff8480 100644 (file)
@@ -386,7 +386,7 @@ http_download(char const *url, char const *path, curl_off_t ims, bool *changed)
        pr_val_info("HTTP GET: %s -> %s", url, path);
 
        /* XXX might not be needed anymore */
-       error = mkdir_p(path, false);
+       error = mkdir_p(path, false, 0777);
        if (error)
                return error;
 
index 6bee4e32b5e7152807889d062d4ef8fffc37cbc4..2dc024cef87fd066cf5436158669dce747e7d200 100644 (file)
@@ -518,7 +518,7 @@ write_file(char const *path, unsigned char *content, size_t content_len)
        size_t written;
        int error;
 
-       error = mkdir_p(path, false);
+       error = mkdir_p(path, false, 0777);
        if (error)
                return error;
 
index 2425a95bf6b507cd6d108318e71ff92739c3e90c..7359664b813cb8a2a99fbea8bc323a0126c3ca07 100644 (file)
@@ -231,7 +231,7 @@ rsync_download(char const *src, char const *dst, bool is_directory)
                        pr_val_debug("    %s", args[i]);
        }
 
-       error = mkdir_p(dst, is_directory);
+       error = mkdir_p(dst, is_directory, 0777);
        if (error)
                goto release_args;
 
index 9b0162e93077d2377e1c4c906694c7a65a4e180b..a8bab970fa6c57f891256aa7b3b5c1c154ce2e11 100644 (file)
@@ -12,7 +12,11 @@ path_rewind(char const *root, char *cursor)
        return NULL;
 }
 
-/* Collapses '//' (after the schema), '.' and '..'. */
+/*
+ * Collapses '//', '.' and '..'. Also removes the colon from the schema.
+ *
+ * "rsync://a.b/./c//.././/d/." -> "rsync/a.b/d"
+ */
 char *
 url_normalize(char const *url)
 {
@@ -24,8 +28,9 @@ url_normalize(char const *url)
                return NULL;
 
        normal = pstrdup(url);
-       dst = normal + RPKI_SCHEMA_LEN;
-       root = dst - 1;
+       root = normal + 5;
+       *root = '/';
+       dst = root + 1;
        token_init(&tkn, url + RPKI_SCHEMA_LEN);
 
        while (token_next(&tkn)) {
@@ -43,7 +48,7 @@ url_normalize(char const *url)
        }
 
        /* Reject URL if there's nothing after the schema. Maybe unnecessary. */
-       if (dst == normal + RPKI_SCHEMA_LEN)
+       if (dst == root + 1)
                goto fail;
 
        dst[-1] = '\0';
index 8bbe63883be730c5921771951fa147f69dd5f6e4..16fa632a04d3995d0abbb80c3918e8417a16139f 100644 (file)
@@ -227,26 +227,26 @@ START_TEST(test_provide)
 {
        struct cache_node *rsync, *abc, *d, *e, *f, *g, *h, *ee;
 
-       rsync = cachent_create_root("rsync:");
+       rsync = cachent_create_root("rsync");
        ck_assert_ptr_ne(NULL, rsync);
        ck_assert_ptr_eq(NULL, rsync->parent);
-       ck_assert_str_eq("rsync:", rsync->url);
-       ck_assert_str_eq("rsync:", rsync->name);
+       ck_assert_str_eq("rsync", rsync->url);
+       ck_assert_str_eq("rsync", rsync->name);
 
        /* Create branch chain from root */
        e = cachent_provide(rsync, "rsync://a.b.c/d/e");
        ck_assert_ptr_ne(NULL, e);
-       ck_assert_str_eq("rsync://a.b.c/d/e", e->url);
+       ck_assert_str_eq("rsync/a.b.c/d/e", e->url);
        ck_assert_str_eq("e", e->name);
 
        d = e->parent;
        ck_assert_ptr_ne(NULL, d);
-       ck_assert_str_eq("rsync://a.b.c/d", d->url);
+       ck_assert_str_eq("rsync/a.b.c/d", d->url);
        ck_assert_str_eq("d", d->name);
 
        abc = d->parent;
        ck_assert_ptr_ne(NULL, abc);
-       ck_assert_str_eq("rsync://a.b.c", abc->url);
+       ck_assert_str_eq("rsync/a.b.c", abc->url);
        ck_assert_str_eq("a.b.c", abc->name);
 
        ck_assert_ptr_eq(rsync, abc->parent);
@@ -273,26 +273,26 @@ START_TEST(test_provide)
        f = cachent_provide(rsync, "rsync://a.b.c/f");
        ck_assert_ptr_ne(NULL, f);
        ck_assert_ptr_eq(abc, f->parent);
-       ck_assert_str_eq("rsync://a.b.c/f", f->url);
+       ck_assert_str_eq("rsync/a.b.c/f", f->url);
        ck_assert_str_eq("f", f->name);
 
        /* Create more than one descendant from root */
        h = cachent_provide(rsync, "rsync://a.b.c/f/g/h");
        ck_assert_ptr_ne(NULL, h);
-       ck_assert_str_eq("rsync://a.b.c/f/g/h", h->url);
+       ck_assert_str_eq("rsync/a.b.c/f/g/h", h->url);
        ck_assert_str_eq("h", h->name);
 
        g = h->parent;
        ck_assert_ptr_ne(NULL, g);
        ck_assert_ptr_eq(f, g->parent);
-       ck_assert_str_eq("rsync://a.b.c/f/g", g->url);
+       ck_assert_str_eq("rsync/a.b.c/f/g", g->url);
        ck_assert_str_eq("g", g->name);
 
        /* Try to create a conflict by prefix */
        ee = cachent_provide(rsync, "rsync://a.b.c/d/ee");
        ck_assert_ptr_ne(e, ee);
        ck_assert_ptr_eq(d, ee->parent);
-       ck_assert_str_eq("rsync://a.b.c/d/ee", ee->url);
+       ck_assert_str_eq("rsync/a.b.c/d/ee", ee->url);
        ck_assert_str_eq("ee", ee->name);
        ck_assert_ptr_eq(e, cachent_provide(abc, "rsync://a.b.c/d/e"));
        ck_assert_ptr_eq(ee, cachent_provide(abc, "rsync://a.b.c/d/ee"));
index 03571a3beac455b98df4ec8974c79eb700e47402..7ad51e816c50a938b189bb9f01682faa8b1b93c9 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "alloc.c"
 #include "common.c"
+#include "file.c"
 //#include "json_util.c"
 #include "mock.c"
 #include "cache/cachent.c"
 
 static unsigned int rsync_counter; /* Times the rsync function was called */
 static unsigned int https_counter; /* Times the https function was called */
-
-struct downloaded_path {
-       char *path;
-       bool visited;
-       SLIST_ENTRY(downloaded_path) hook;
-};
-
-
-static bool dl_mock_type; /* false = list. true = list + actual files */
 static int dl_error;
 
-/* Paths downloaded during the test */
-static SLIST_HEAD(downloaded_paths, downloaded_path) downloaded;
-
-int
-file_exists(char const *path)
-{
-       struct stat meta;
-       struct downloaded_path *dp;
-
-       if (dl_mock_type)
-               return (stat(path, &meta) == 0) ? 0 : errno;
-
-       SLIST_FOREACH(dp, &downloaded, hook)
-               if (strcmp(path, dp->path) == 0)
-                       return 0;
-       return ENOENT;
-}
-
-int
-file_rm_rf(char const *file)
-{
-       struct downloaded_path *path;
-
-       SLIST_FOREACH(path, &downloaded, hook)
-               if (strcmp(file, path->path) == 0) {
-                       SLIST_REMOVE(&downloaded, path, downloaded_path, hook);
-                       free(path->path);
-                       free(path);
-                       if (dl_mock_type)
-                               ck_assert_int_eq(0, remove(file));
-                       return 0;
-               }
-
-       return ENOENT;
-}
-
-int
-file_rm_f(char const *file)
-{
-       file_rm_rf(file);
-       return 0;
-}
-
-MOCK_ABORT_INT(file_get_mtim, char const *file, time_t *ims)
-
 static void
 __delete_node_cb(struct cache_node const *node)
 {
        /* Nothing */
 }
 
-static int
-pretend_download(char const *local)
+int
+rsync_download(char const *src, char const *dst, bool is_directory)
 {
-       struct downloaded_path *dl;
+       char cmd[64];
+
+       rsync_counter++;
 
        if (dl_error)
                return dl_error;
-       if (file_exists(local) == 0)
-               return 0;
 
-       dl = pmalloc(sizeof(struct downloaded_path));
-       dl->path = pstrdup(local);
-       dl->visited = false;
-       SLIST_INSERT_HEAD(&downloaded, dl, hook);
+       ck_assert_int_eq(0, mkdir_p(dst, true, 0777));
 
-       if (dl_mock_type)
-               ck_assert_int_eq(0, mkdir_p(local, true));
+       ck_assert(snprintf(cmd, sizeof(cmd), "touch %s/file", dst) < sizeof(cmd));
+       ck_assert_int_eq(0, system(cmd));
 
        return 0;
 }
 
-int
-rsync_download(char const *src, char const *dst, bool is_directory)
-{
-       rsync_counter++;
-       return pretend_download(dst);
-}
-
 int
 http_download(char const *url, char const *path, curl_off_t ims, bool *changed)
 {
-       int error;
+       char cmd[61];
+
        https_counter++;
-       error = pretend_download(path);
-       if (changed != NULL)
-               *changed = error ? false : true;
-       return error;
+
+       if (dl_error) {
+               *changed = false;
+               return dl_error;
+       }
+
+       ck_assert_int_eq(0, mkdir_p(path, false, 0777));
+
+       ck_assert(snprintf(cmd, sizeof(cmd), "touch %s", path) < sizeof(cmd));
+       ck_assert_int_eq(0, system(cmd));
+
+       *changed = true;
+       return 0;
 }
 
 MOCK_ABORT_INT(rrdp_update, struct cache_node *notif)
 __MOCK_ABORT(rrdp_notif2json, json_t *, NULL, struct cachefile_notification *notif)
 MOCK_VOID(rrdp_notif_free, struct cachefile_notification *notif)
 MOCK_ABORT_INT(rrdp_json2notif, json_t *json, struct cachefile_notification **result)
-MOCK(cfg_cache_threshold, time_t, get_days_ago(7), void)
+MOCK(cfg_cache_threshold, time_t, 60 * 60 * 24 * 7, void)
 
 /* Helpers */
 
@@ -135,11 +82,10 @@ static void
 setup_test(bool dl_type)
 {
        dl_error = 0;
-       dl_mock_type = dl_type;
-       SLIST_INIT(&downloaded);
-
        ck_assert_int_eq(0, system("rm -rf tmp/"));
        cache_prepare();
+       ck_assert_int_eq(0, system("mkdir -p tmp/rsync"));
+       ck_assert_int_eq(0, system("mkdir -p tmp/https"));
 }
 
 static int
@@ -169,67 +115,22 @@ run_dl_rsync(char const *caRepository, int expected_error,
        sias_cleanup(&sias);
 }
 
-static void
-reset_visiteds(void)
-{
-       struct downloaded_path *path;
-       SLIST_FOREACH(path, &downloaded, hook)
-               path->visited = false;
-}
-
-static struct downloaded_path *
-find_downloaded_path(struct cache_node *node)
+static bool
+ck_path(struct cache_node *node, char const *_)
 {
-       struct downloaded_path *path;
+       int error;
 
        if (!node->tmpdir)
-               return NULL;
-
-       if (dl_mock_type && !file_exists(node->tmpdir))
-               return NULL;
-
-       SLIST_FOREACH(path, &downloaded, hook) {
-               if (strcmp(node->tmpdir, path->path) == 0) {
-                       if (path->visited)
-                               ck_abort_msg("Looked up twice: %s", path->path);
-                       path->visited = true;
-                       return path;
-               }
-       }
+               return true;
 
-       return NULL;
-}
-
-static bool
-check_path(struct cache_node *node, char const *_)
-{
-       struct downloaded_path *path;
-
-       PR_DEBUG_MSG("Checking %s", node->url);
-
-       path = find_downloaded_path(node);
-       if (node->tmpdir) {
-               if (path == NULL)
-                       ck_abort_msg("Cached file is missing: %s",
-                           node->tmpdir);
-       } else {
-               if (path != NULL)
-                       ck_abort_msg("Cached file should not exist: %s",
-                           path->path);
-       }
+       PR_DEBUG_MSG("Checking file exists in cache: %s (%s)", node->tmpdir, node->url);
+       error = file_exists(node->tmpdir);
+       if (error)
+               ck_abort_msg("Missing file in cache: %s (%s)", node->tmpdir, strerror(error));
 
        return true;
 }
 
-static void
-fail_if_nonvisited(void)
-{
-       struct downloaded_path *path;
-       SLIST_FOREACH(path, &downloaded, hook)
-               if (!path->visited)
-                       ck_abort_msg("Unexpected cache file: %s", path->path);
-}
-
 //static struct cache_node *
 //cachent_find(struct cache_node *root, char const *url)
 //{
@@ -267,7 +168,7 @@ ck_assert_cachent_eq(struct cache_node *expected, struct cache_node *actual)
 {
        struct cache_node *echild, *achild, *tmp;
 
-       PR_DEBUG_MSG("Comparing %s", expected->url);
+       PR_DEBUG_MSG("Comparing %s vs %s", expected->url, actual->url);
 
        ck_assert_str_eq(expected->url, actual->url);
        ck_assert_str_eq(expected->name, actual->name);
@@ -289,11 +190,17 @@ ck_assert_cachent_eq(struct cache_node *expected, struct cache_node *actual)
        }
 }
 
+static int
+print_file(const char *fpath, const struct stat *sb, int typeflag,
+    struct FTW *ftwbuf)
+{
+       printf("- %s\n", fpath);
+       return 0;
+}
+
 static void
 ck_cache(struct cache_node *rsync, struct cache_node *https)
 {
-       struct downloaded_path *path;
-
        printf("------------------------------\n");
 
        printf("Expected nodes:\n");
@@ -306,17 +213,17 @@ ck_cache(struct cache_node *rsync, struct cache_node *https)
        printf("\n");
 
        printf("Files in cache:\n");
-       SLIST_FOREACH(path, &downloaded, hook)
-               printf("- %s\n", path->path);
+       ck_assert_int_eq(0, nftw("tmp/", print_file, 32, FTW_PHYS));
        printf("\n");
 
        /* Compare expected and cache */
-       reset_visiteds();
-       cachent_traverse(rsync, check_path);
-       cachent_traverse(https, check_path);
-       fail_if_nonvisited();
+       // XXX fix
+       PR_DEBUG_MSG("%s", ">> Comparing expected and cache...");
+       cachent_traverse(rsync, ck_path);
+       cachent_traverse(https, ck_path);
 
        /* Compare expected and actual */
+       PR_DEBUG_MSG("%s", ">> Comparing expected and actual...");
        ck_assert_cachent_eq(rsync, cache.rsync);
        ck_assert_cachent_eq(https, cache.https);
 
@@ -327,7 +234,7 @@ ck_cache(struct cache_node *rsync, struct cache_node *https)
 static void
 ck_cache_rsync(struct cache_node *rsync)
 {
-       ck_cache(rsync, unode("https:", NULL));
+       ck_cache(rsync, unode("https", NULL));
 }
 
 static time_t epoch;
@@ -335,16 +242,36 @@ static time_t epoch;
 static bool
 unfreshen(struct cache_node *node, char const *path)
 {
+       PR_DEBUG_MSG("Unfreshening %s.", node->url);
        node->flags &= ~CNF_FRESH;
        node->mtim = epoch;
        return true;
 }
 
+static int
+nftw_unfreshen(const char *fpath, const struct stat *sb, int typeflag,
+    struct FTW *ftwbuf)
+{
+       struct timespec times[2];
+
+       times[0].tv_sec = epoch;
+       times[0].tv_nsec = 0;
+       times[1].tv_sec = epoch;
+       times[1].tv_nsec = 0;
+       PR_DEBUG_MSG("changing times of %s", fpath);
+
+       ck_assert_int_eq(0, utimensat(AT_FDCWD, fpath, times, AT_SYMLINK_NOFOLLOW));
+
+       return 0;
+}
+
 static void
 new_iteration(bool outdate)
 {
        epoch = outdate ? get_days_ago(30) : get_days_ago(1);
        cachent_traverse(cache.rsync, unfreshen);
+       ck_assert_int_eq(0, nftw("tmp/rsync", nftw_unfreshen, 32, FTW_PHYS));
+       ck_assert_int_eq(0, nftw("tmp/https", nftw_unfreshen, 32, FTW_PHYS));
 }
 
 //static void
@@ -358,17 +285,9 @@ new_iteration(bool outdate)
 static void
 cleanup_test(void)
 {
-       struct downloaded_path *path;
-
        dl_error = 0;
        cache_commit();
-
-       while (!SLIST_EMPTY(&downloaded)) {
-               path = SLIST_FIRST(&downloaded);
-               SLIST_REMOVE_HEAD(&downloaded, hook);
-               free(path->path);
-               free(path);
-       }
+       ck_assert_int_eq(0, system("rm -rf tmp/"));
 }
 
 /* Tests */
@@ -380,23 +299,23 @@ static const int STALE = CNF_RSYNC | CNF_CACHED | CNF_VALID;
 /* Intermediary between a downloaded and a validated node */
 //static const int BRANCH = RSYNC_INHERIT;
 //static const int FAILED = CNF_FRESH;
-//
+
 //START_TEST(test_cache_download_rsync)
 //{
 //     setup_test(false);
 //
 //     run_dl_rsync("rsync://a.b.c/d", 0, 1);
 //     ck_cache_rsync(
-//             unode("rsync:",
-//                     unode("rsync://a.b.c",
-//                             uftnode("rsync://a.b.c/d", FULL, "tmp/tmp/0", NULL), NULL), NULL));
+//             unode("rsync",
+//                     unode("rsync/a.b.c",
+//                             uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL), NULL), NULL));
 //
 //     /* Redownload same file, nothing should happen */
 //     run_dl_rsync("rsync://a.b.c/d", 0, 0);
 //     ck_cache_rsync(
-//             unode("rsync:",
-//                     unode("rsync://a.b.c",
-//                             uftnode("rsync://a.b.c/d", FULL, "tmp/tmp/0", NULL), NULL), NULL));
+//             unode("rsync",
+//                     unode("rsync/a.b.c",
+//                             uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL), NULL), NULL));
 //
 //     /*
 //      * rsyncs are recursive, which means if we've been recently asked to
@@ -404,10 +323,10 @@ static const int STALE = CNF_RSYNC | CNF_CACHED | CNF_VALID;
 //      */
 //     run_dl_rsync("rsync://a.b.c/d/e", 0, 0);
 //     ck_cache_rsync(
-//             unode("rsync:",
-//                     unode("rsync://a.b.c",
-//                             uftnode("rsync://a.b.c/d", FULL, "tmp/tmp/0",
-//                                     ufnode("rsync://a.b.c/d/e", VALIDATED, NULL), NULL), NULL), NULL));
+//             unode("rsync",
+//                     unode("rsync/a.b.c",
+//                             uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0",
+//                                     ufnode("rsync/a.b.c/d/e", VALIDATED, NULL), NULL), NULL), NULL));
 //
 //     /*
 //      * rsyncs get truncated, because it results in much faster
@@ -417,28 +336,28 @@ static const int STALE = CNF_RSYNC | CNF_CACHED | CNF_VALID;
 //      */
 //     run_dl_rsync("rsync://x.y.z/m/n/o", 0, 1);
 //     ck_cache_rsync(
-//             unode("rsync:",
-//                     unode("rsync://a.b.c",
-//                             uftnode("rsync://a.b.c/d", FULL, "tmp/tmp/0",
-//                                     ufnode("rsync://a.b.c/d/e", VALIDATED, NULL), NULL), NULL),
-//                     unode("rsync://x.y.z",
-//                             uftnode("rsync://x.y.z/m", DOWNLOADED, "tmp/tmp/1",
-//                                     ufnode("rsync://x.y.z/m/n", BRANCH,
-//                                             ufnode("rsync://x.y.z/m/n/o", VALIDATED, NULL), NULL), NULL), NULL), NULL));
+//             unode("rsync",
+//                     unode("rsync/a.b.c",
+//                             uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0",
+//                                     ufnode("rsync/a.b.c/d/e", VALIDATED, NULL), NULL), NULL),
+//                     unode("rsync/x.y.z",
+//                             uftnode("rsync/x.y.z/m", DOWNLOADED, "tmp/tmp/1",
+//                                     ufnode("rsync/x.y.z/m/n", BRANCH,
+//                                             ufnode("rsync/x.y.z/m/n/o", VALIDATED, NULL), NULL), NULL), NULL), NULL));
 //
 //     /* Sibling */
 //     run_dl_rsync("rsync://a.b.c/e/f", 0, 1);
 //     ck_cache_rsync(
-//             unode("rsync:",
-//                     unode("rsync://a.b.c",
-//                             uftnode("rsync://a.b.c/d", FULL, "tmp/tmp/0",
-//                                     ufnode("rsync://a.b.c/d/e", VALIDATED, NULL), NULL),
-//                             uftnode("rsync://a.b.c/e", DOWNLOADED, "tmp/tmp/2",
-//                                     ufnode("rsync://a.b.c/e/f", VALIDATED, NULL), NULL), NULL),
-//                     unode("rsync://x.y.z",
-//                             uftnode("rsync://x.y.z/m", DOWNLOADED, "tmp/tmp/1",
-//                                     ufnode("rsync://x.y.z/m/n", BRANCH,
-//                                             ufnode("rsync://x.y.z/m/n/o", VALIDATED, NULL), NULL), NULL), NULL), NULL));
+//             unode("rsync",
+//                     unode("rsync/a.b.c",
+//                             uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0",
+//                                     ufnode("rsync/a.b.c/d/e", VALIDATED, NULL), NULL),
+//                             uftnode("rsync/a.b.c/e", DOWNLOADED, "tmp/tmp/2",
+//                                     ufnode("rsync/a.b.c/e/f", VALIDATED, NULL), NULL), NULL),
+//                     unode("rsync/x.y.z",
+//                             uftnode("rsync/x.y.z/m", DOWNLOADED, "tmp/tmp/1",
+//                                     ufnode("rsync/x.y.z/m/n", BRANCH,
+//                                             ufnode("rsync/x.y.z/m/n/o", VALIDATED, NULL), NULL), NULL), NULL), NULL));
 //
 //     cleanup_test();
 //}
@@ -453,27 +372,27 @@ static const int STALE = CNF_RSYNC | CNF_CACHED | CNF_VALID;
 //     dl_error = -EINVAL;
 //     run_dl_rsync("rsync://a.b.c/e", -EINVAL, 1);
 //     ck_cache_rsync(
-//             unode("rsync:",
-//                     unode("rsync://a.b.c",
-//                             uftnode("rsync://a.b.c/d", FULL, "tmp/tmp/0", NULL),
-//                             ufnode("rsync://a.b.c/e", FAILED, NULL), NULL), NULL));
+//             unode("rsync",
+//                     unode("rsync/a.b.c",
+//                             uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL),
+//                             ufnode("rsync/a.b.c/e", FAILED, NULL), NULL), NULL));
 //
 //     /* Regardless of error, not reattempted because same iteration */
 //     dl_error = EINVAL;
 //     run_dl_rsync("rsync://a.b.c/e", -EINVAL, 0);
 //     ck_cache_rsync(
-//             unode("rsync:",
-//                     unode("rsync://a.b.c",
-//                             uftnode("rsync://a.b.c/d", FULL, "tmp/tmp/0", NULL),
-//                             ufnode("rsync://a.b.c/e", FAILED, NULL), NULL), NULL));
+//             unode("rsync",
+//                     unode("rsync/a.b.c",
+//                             uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL),
+//                             ufnode("rsync/a.b.c/e", FAILED, NULL), NULL), NULL));
 //
 //     dl_error = 0;
 //     run_dl_rsync("rsync://a.b.c/e", -EINVAL, 0);
 //     ck_cache_rsync(
-//             unode("rsync:",
-//                     unode("rsync://a.b.c",
-//                             uftnode("rsync://a.b.c/d", FULL, "tmp/tmp/0", NULL),
-//                             ufnode("rsync://a.b.c/e", FAILED, NULL), NULL), NULL));
+//             unode("rsync",
+//                     unode("rsync/a.b.c",
+//                             uftnode("rsync/a.b.c/d", FULL, "tmp/tmp/0", NULL),
+//                             ufnode("rsync/a.b.c/e", FAILED, NULL), NULL), NULL));
 //
 //     cleanup_test();
 //}
@@ -487,76 +406,89 @@ START_TEST(test_cache_cleanup_rsync)
         * First iteration: Tree is created. No prunes, because nothing's
         * outdated.
         */
+       PR_DEBUG;
        new_iteration(true);
        run_dl_rsync("rsync://a.b.c/d", 0, 1);
        run_dl_rsync("rsync://a.b.c/e", 0, 1);
        cleanup_cache();
        ck_cache_rsync(
-               unode("rsync:",
-                       unode("rsync://a.b.c",
-                               ufnode("rsync://a.b.c/d", FULL, NULL),
-                               ufnode("rsync://a.b.c/e", FULL, NULL), NULL), NULL));
+               unode("rsync",
+                       unode("rsync/a.b.c",
+                               ufnode("rsync/a.b.c/d", FULL, NULL),
+                               ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL));
 
        /* One iteration with no changes, for paranoia */
+       PR_DEBUG;
        new_iteration(true);
        run_dl_rsync("rsync://a.b.c/d", 0, 1);
        run_dl_rsync("rsync://a.b.c/e", 0, 1);
        cleanup_cache();
        ck_cache_rsync(
-               unode("rsync:",
-                       unode("rsync://a.b.c",
-                               ufnode("rsync://a.b.c/d", FULL, NULL),
-                               ufnode("rsync://a.b.c/e", FULL, NULL), NULL), NULL));
+               unode("rsync",
+                       unode("rsync/a.b.c",
+                               ufnode("rsync/a.b.c/d", FULL, NULL),
+                               ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL));
 
        /* Add one sibling */
+       PR_DEBUG;
        new_iteration(true);
        run_dl_rsync("rsync://a.b.c/d", 0, 1);
        run_dl_rsync("rsync://a.b.c/e", 0, 1);
        run_dl_rsync("rsync://a.b.c/f", 0, 1);
        cleanup_cache();
        ck_cache_rsync(
-               unode("rsync:",
-                       unode("rsync://a.b.c",
-                               ufnode("rsync://a.b.c/d", FULL, NULL),
-                               ufnode("rsync://a.b.c/e", FULL, NULL),
-                               ufnode("rsync://a.b.c/f", FULL, NULL), NULL), NULL));
+               unode("rsync",
+                       unode("rsync/a.b.c",
+                               ufnode("rsync/a.b.c/d", FULL, NULL),
+                               ufnode("rsync/a.b.c/e", FULL, NULL),
+                               ufnode("rsync/a.b.c/f", FULL, NULL), NULL), NULL));
 
        /* Nodes don't get updated, but they're still too young. */
+       PR_DEBUG;
        new_iteration(false);
        cleanup_cache();
        ck_cache_rsync(
-               unode("rsync:",
-                       unode("rsync://a.b.c",
-                               ufnode("rsync://a.b.c/d", STALE, NULL),
-                               ufnode("rsync://a.b.c/e", STALE, NULL),
-                               ufnode("rsync://a.b.c/f", STALE, NULL), NULL), NULL));
+               unode("rsync",
+                       unode("rsync/a.b.c",
+                               ufnode("rsync/a.b.c/d", STALE, NULL),
+                               ufnode("rsync/a.b.c/e", STALE, NULL),
+                               ufnode("rsync/a.b.c/f", STALE, NULL), NULL), NULL));
 
        /* Remove some branches */
        new_iteration(true);
        run_dl_rsync("rsync://a.b.c/d", 0, 1);
        cleanup_cache();
        ck_cache_rsync(
-               unode("rsync:",
-                       unode("rsync://a.b.c",
-                               ufnode("rsync://a.b.c/d", FULL, NULL), NULL), NULL));
+               unode("rsync",
+                       unode("rsync/a.b.c",
+                               ufnode("rsync/a.b.c/d", FULL, NULL), NULL), NULL));
+
+       /* Remove old branch and add sibling at the same time */
+       new_iteration(true);
+       run_dl_rsync("rsync://a.b.c/e", 0, 1);
+       cleanup_cache();
+       ck_cache_rsync(
+               unode("rsync",
+                       unode("rsync/a.b.c",
+                               ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL));
+
+       /* Try child */
+       new_iteration(true);
+       run_dl_rsync("rsync://a.b.c/e/f/g", 0, 1);
+       cleanup_cache();
+       ck_cache_rsync(
+               unode("rsync",
+                       unode("rsync/a.b.c",
+                               ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL));
 
-//     /* Remove old branch and add sibling at the same time */
-//     new_iteration(true);
-//     run_dl_rsync("rsync://a.b.c/e", 0, 1);
-//     cleanup_cache();
-//     ck_cache(NODE("rsync://a.b.c/e/", 0, 1, true), NULL);
-//
-//     /* Try child */
-//     new_iteration(true);
-//     run_dl_rsync("rsync://a.b.c/e/f/g", 0, 1);
-//     cleanup_cache();
-//     ck_cache(NODE("rsync://a.b.c/e/", 0, 1, true), NULL);
-//
 //     /* Parent again */
 //     new_iteration(true);
 //     run_dl_rsync("rsync://a.b.c/e", 0, 1);
 //     cleanup_cache();
-//     ck_cache(NODE("rsync://a.b.c/e/", 0, 1, true), NULL);
+//     ck_cache_rsync(
+//             unode("rsync",
+//                     unode("rsync/a.b.c",
+//                             ufnode("rsync/a.b.c/e", FULL, NULL), NULL), NULL));
 //
 //     /* Empty the tree */
 //     new_iteration(true);
@@ -928,18 +860,18 @@ END_TEST
 //      */
 //     cache_reset(cache);
 //
-//     add_node(cache, node("rsync://a/1", 100, 0, 1, 100, 0));
-//     add_node(cache, node("rsync://a/2", 100, 1, 1, 100, 0));
-//     add_node(cache, node("rsync://a/3", 200, 0, 1, 100, 0));
-//     add_node(cache, node("rsync://a/4", 200, 1, 1, 100, 0));
-//     add_node(cache, node("rsync://a/5", 100, 0, 1, 200, 0));
-//     add_node(cache, node("rsync://a/6", 100, 1, 1, 200, 0));
-//     add_node(cache, node("rsync://b/1", 100, 0, 0, 100, 0));
-//     add_node(cache, node("rsync://b/2", 100, 1, 0, 100, 0));
-//     add_node(cache, node("rsync://b/3", 200, 0, 0, 100, 0));
-//     add_node(cache, node("rsync://b/4", 200, 1, 0, 100, 0));
-//     add_node(cache, node("rsync://b/5", 100, 0, 0, 200, 0));
-//     add_node(cache, node("rsync://b/6", 100, 1, 0, 200, 0));
+//     add_node(cache, node("rsync/a/1", 100, 0, 1, 100, 0));
+//     add_node(cache, node("rsync/a/2", 100, 1, 1, 100, 0));
+//     add_node(cache, node("rsync/a/3", 200, 0, 1, 100, 0));
+//     add_node(cache, node("rsync/a/4", 200, 1, 1, 100, 0));
+//     add_node(cache, node("rsync/a/5", 100, 0, 1, 200, 0));
+//     add_node(cache, node("rsync/a/6", 100, 1, 1, 200, 0));
+//     add_node(cache, node("rsync/b/1", 100, 0, 0, 100, 0));
+//     add_node(cache, node("rsync/b/2", 100, 1, 0, 100, 0));
+//     add_node(cache, node("rsync/b/3", 200, 0, 0, 100, 0));
+//     add_node(cache, node("rsync/b/4", 200, 1, 0, 100, 0));
+//     add_node(cache, node("rsync/b/5", 100, 0, 0, 200, 0));
+//     add_node(cache, node("rsync/b/6", 100, 1, 0, 200, 0));
 //
 //     /* Multiple successful caches: Prioritize the most recent one */
 //     PREPARE_MAP_LIST(&maps, "rsync://a/1", "rsync://a/3", "rsync://a/5");
index b0bb560df20c64bb9909575d04372c28603af268..e2849c13e7656956aff83b6f8120d62a0fa02ae8 100644 (file)
@@ -16,8 +16,8 @@
 MOCK_TRUE(log_val_enabled, unsigned int l)
 MOCK_TRUE(log_op_enabled, unsigned int l)
 
-/* CFLAGS=-DPRINT_PRS make check */
-#ifdef PRINT_PRS
+///* CFLAGS=-DPRINT_PRS make check */
+//#ifdef PRINT_PRS
 #define MOCK_PRINT                                                     \
        do {                                                            \
                va_list args;                                           \
@@ -26,9 +26,9 @@ MOCK_TRUE(log_op_enabled, unsigned int l)
                va_end(args);                                           \
                printf("\n");                                           \
        } while (0)
-#else
-#define MOCK_PRINT
-#endif
+//#else
+//#define MOCK_PRINT
+//#endif
 
 #define MOCK_VOID_PRINT(name)                                          \
        void                                                            \
index 0497cb87a88f78961f5bfe24a2888fa7e70d8a55..763843b1b28898a9b33bfe09a31a79cd731a16c0 100644 (file)
@@ -15,16 +15,16 @@ START_TEST(test_normalize)
 {
        char *normal;
 
-       TEST_NORMALIZE("rsync://a.b.c", "rsync://a.b.c");
-       TEST_NORMALIZE("rsync://a.b.c/", "rsync://a.b.c");
-       TEST_NORMALIZE("rsync://a.b.c//////", "rsync://a.b.c");
-       TEST_NORMALIZE("rsync://a.b.c/d/e", "rsync://a.b.c/d/e");
-       TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync://a.b.c/d/e");
-       TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync://a.b.c/d/e");
-       TEST_NORMALIZE("rsync://a.b.c/d/./e/.", "rsync://a.b.c/d/e");
-       TEST_NORMALIZE("rsync://a.b.c/d/../d/../d/e/", "rsync://a.b.c/d/e");
-       TEST_NORMALIZE("rsync://a.b.c/../x/y/z", "rsync://x/y/z");
-       TEST_NORMALIZE("rsync://x//y/z/../../../m/./n/o", "rsync://m/n/o");
+       TEST_NORMALIZE("rsync://a.b.c", "rsync/a.b.c");
+       TEST_NORMALIZE("rsync://a.b.c/", "rsync/a.b.c");
+       TEST_NORMALIZE("rsync://a.b.c//////", "rsync/a.b.c");
+       TEST_NORMALIZE("rsync://a.b.c/d/e", "rsync/a.b.c/d/e");
+       TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync/a.b.c/d/e");
+       TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync/a.b.c/d/e");
+       TEST_NORMALIZE("rsync://a.b.c/d/./e/.", "rsync/a.b.c/d/e");
+       TEST_NORMALIZE("rsync://a.b.c/d/../d/../d/e/", "rsync/a.b.c/d/e");
+       TEST_NORMALIZE("rsync://a.b.c/../x/y/z", "rsync/x/y/z");
+       TEST_NORMALIZE("rsync://x//y/z/../../../m/./n/o", "rsync/m/n/o");
        ck_assert_ptr_eq(NULL, url_normalize("rsync://"));
        ck_assert_ptr_eq(NULL, url_normalize("rsync://.."));
        ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/.."));