*
* - We only need to keep nodes for the rsync root.
* - The tree traverse only needs to touch files.
+ * - RRDP needs caging.
*/
#include "cache/local_cache.h"
return 0;
}
-static char *
-get_tal_json_filename(void)
-{
- struct path_builder pb;
- return pb_init_cache(&pb, TAL_METAFILE) ? NULL : pb.string;
-}
-
-static struct cache_node *
-json2node(json_t *json)
-{
+//static char *
+//get_tal_json_filename(void)
+//{
+// struct path_builder pb;
+// return pb_init_cache(&pb, TAL_METAFILE) ? NULL : pb.string;
+//}
+//
+//static struct cache_node *
+//json2node(json_t *json)
+//{
// struct cache_node *node;
// char const *type_str;
// enum map_type type;
// map_refput(node->map);
// rrdp_notif_free(node->notif);
// free(node);
- return NULL;
-}
+// return NULL;
+//}
static void
load_tal_json(void)
load_tal_json();
}
-static json_t *
-node2json(struct cache_node *node)
-{
+//static json_t *
+//node2json(struct cache_node *node)
+//{
// json_t *json;
// char const *type;
// json_t *notification;
//
//cancel:
// json_decref(json);
- return NULL;
-}
-
-static json_t *
-build_tal_json(struct rpki_cache *cache)
-{
+// return NULL;
+//}
+//
+//static json_t *
+//build_tal_json(struct rpki_cache *cache)
+//{
// struct cache_node *node, *tmp;
// json_t *root, *child;
//
// root = json_array_new();
// if (root == NULL)
- return NULL;
-
+// return NULL;
+//
// HASH_ITER(hh, cache->ht, node, tmp) {
// child = node2json(node);
// if (child != NULL && json_array_append_new(root, child)) {
// }
//
// return root;
-}
+//}
static void
write_tal_json(void)
return node;
}
-static struct cache_node *
-get_rsync_rpp(char const *caRepository, struct cache_node *rpkiManifest)
+static int
+dl_rrdp(struct cache_node *rpp)
{
- struct cache_node *node;
- char *normal;
+ int error;
- normal = url_normalize(caRepository);
- if (normal == NULL)
- return NULL;
+ if (!config_get_http_enabled()) {
+ pr_val_debug("HTTP is disabled.");
+ return 1;
+ }
- for (node = rpkiManifest; node != NULL; node = node->parent)
- if (strcmp(node->url, normal) == 0) {
- free(normal);
- return node;
- }
+ // XXX needs to add all files to node.
+ // Probably also update node itself.
+ // XXX maybe pr_crit() on !mft->parent?
+ error = rrdp_update(rpp);
+ if (error)
+ pr_val_debug("RRDP RPP: Failed refresh.");
- free(normal);
- return NULL;
+ return error;
}
static int
-dl_rsync(char const *caRepository, struct cache_node *mft)
+dl_rsync(struct cache_node *rpp)
{
struct cache_node *module, *node;
char *path;
return 1;
}
- module = get_rsync_module(mft);
- if (module == NULL) {
+ module = get_rsync_module(rpp);
+ if (module == NULL)
return -EINVAL; // XXX
- }
- mft->rpp = get_rsync_rpp(caRepository, mft);
- if (!mft->rpp)
- return pr_val_err("Manifest '%s' does not seem to be inside its publication point '%s'.",
- mft->url, caRepository);
error = cache_tmpfile(&path);
if (error)
module->mtim = time(NULL); // XXX catch -1
module->tmpdir = path;
- for (node = mft; node != module; node = node->parent) {
+ for (node = rpp; node != module; node = node->parent) {
node->flags |= RSYNC_INHERIT;
node->mtim = module->mtim;
- if (mft) {
- node->rpp = mft->rpp;
- if (node == mft->rpp)
- mft = NULL;
- }
}
return 0;
}
+/*
static int
dl_http(struct cache_node *node)
{
return http_download_cache_node(node);
}
+*/
+/* @uri is either a caRepository or a rpkiNotify */
static int
-dl_rrdp(char const *notif_url, struct cache_node *mft)
-{
- if (!config_get_http_enabled()) {
- pr_val_debug("HTTP is disabled.");
- return 1;
- }
-
- // XXX needs to add all files to node. Probably also update node itself.
- // XXX maybe pr_crit() on !mft->parent?
- return rrdp_update(cachent_provide(cache.https, notif_url), mft->parent);
-
-// node->flags |= CNF_FRESH;
-// node->mtim = time(NULL); // XXX catch -1
-// node->tmpdir = path;
-}
-
-static int
-download(char const *uri, enum map_type type, struct cache_node *mft)
+try_uri(char const *uri, int (*download)(struct cache_node *),
+ maps_dl_cb validate, void *arg)
{
- switch (type) {
- case MAP_RSYNC:
- return dl_rsync(uri, mft);
- case MAP_HTTP:
- return dl_http(mft);
- case MAP_NOTIF:
- return dl_rrdp(uri, mft);
- }
+ struct cache_node *rpp;
+ int error;
- pr_crit("Unreachable.");
- return -EINVAL; /* Warning shutupper */
-}
+ if (!uri)
+ return 1; /* Protocol unavailable; ignore */
-/*
- * XXX review result sign
- *
- * uri is a rpkiNotify or a caRepository.
- */
-static int
-try_uri(struct cache_node *mft, char const *uri, enum map_type type,
- bool online, maps_dl_cb cb, void *arg)
-{
- int error;
+ pr_val_debug("Trying %s (%s)...", uri, download ? "online" : "offline");
- pr_val_debug("Trying %s...", uri);
+ rpp = cachent_provide(cache.rsync, uri);
+ if (!rpp)
+ return pr_val_err("Malformed URL: %s", uri);
- if (online) {
- error = download(uri, type, mft);
- if (error) {
- pr_val_debug("RPP refresh failed.");
- return error;
+ if (download != NULL) {
+ if (rpp->flags & CNF_FRESH) {
+ if (rpp->dlerr)
+ return rpp->dlerr;
+ } else {
+ rpp->flags |= CNF_FRESH;
+ error = rpp->dlerr = download(rpp);
+ if (error)
+ return error;
}
}
- error = cb(mft->rpp, arg);
+ error = validate(rpp, arg);
if (error) {
pr_val_debug("RPP validation failed.");
return error;
}
/* XXX commit the files (later, during cleanup) */
- pr_val_debug("RPP downloaded and validated successfully.");
+ pr_val_debug("RPP validated successfully.");
return 0;
}
/**
+ * XXX outdated comment
+ *
* Assumes the URIs represent different ways to access the same content.
*
* Sequentially (in the order dictated by their priorities) attempts to update
int
cache_download_alt(struct sia_uris *uris, maps_dl_cb cb, void *arg)
{
- struct cache_node *mft;
- int online;
- int error = 0;
+ int error;
- /* XXX mutex */
- /* XXX if parent is downloaded, child is downloaded. */
- mft = cachent_provide(cache.rsync, uris->rpkiManifest);
+ // XXX Make sure somewhere validates rpkiManifest matches caRepository.
- if (mft->flags & CNF_FRESH)
- return cb(mft->rpp, arg); // XXX can rpp be NULL?
+ /* XXX mutex */
+// /* XXX if parent is downloaded, child is downloaded. */
+// mft = cachent_provide(cache.rsync, uris->rpkiManifest);
+//
+// if (mft->flags & CNF_FRESH)
+// return cb(mft->rpp, arg); // XXX can rpp be NULL?
- for (online = 1; online >= 0; online--) {
- if (uris->rpkiNotify) {
- error = try_uri(mft, uris->rpkiNotify, MAP_NOTIF,
- online, cb, arg);
- if (error <= 0)
- return error;
- }
- error = try_uri(mft, uris->caRepository, MAP_RSYNC,
- online, cb, arg);
- if (error <= 0)
- return error;
- }
+ /* Online attempts */
+ // XXX review result signs
+ // XXX normalize rpkiNotify & caRepository?
+ error = try_uri(uris->rpkiNotify, dl_rrdp, cb, arg);
+ if (error <= 0)
+ return error;
+ error = try_uri(uris->caRepository, dl_rsync, cb, arg);
+ if (error <= 0)
+ return error;
- return error;
+ /* Offline attempts */
+ error = try_uri(uris->rpkiNotify, NULL, cb, arg);
+ if (error <= 0)
+ return error;
+ return try_uri(uris->caRepository, NULL, cb, arg);
}
void
static bool
commit_rpp_delta(struct cache_node *node, char const *path)
{
+ PR_DEBUG_MSG("Commiting %s", node->url);
+
if (node->tmpdir == NULL)
return true; /* Not updated */
//
// delete_node(cache, node);
//}
-//
-//static time_t
-//get_days_ago(int days)
-//{
-// time_t tt_now, last_week;
-// struct tm tm;
-// int error;
-//
-// tt_now = time(NULL);
-// if (tt_now == (time_t) -1)
-// pr_crit("time(NULL) returned (time_t) -1.");
-// if (localtime_r(&tt_now, &tm) == NULL) {
-// error = errno;
-// pr_crit("localtime_r(tt, &tm) returned error: %s",
-// strerror(error));
-// }
-// tm.tm_mday -= days;
-// last_week = mktime(&tm);
-// if (last_week == (time_t) -1)
-// pr_crit("mktime(tm) returned (time_t) -1.");
-//
-// return last_week;
-//}
-//
+
+static time_t
+get_days_ago(int days)
+{
+ time_t tt_now, last_week;
+ struct tm tm;
+ int error;
+
+ tt_now = time(NULL);
+ if (tt_now == (time_t) -1)
+ pr_crit("time(NULL) returned (time_t) -1.");
+ if (localtime_r(&tt_now, &tm) == NULL) {
+ error = errno;
+ pr_crit("localtime_r(tt, &tm) returned error: %s",
+ strerror(error));
+ }
+ tm.tm_mday -= days;
+ last_week = mktime(&tm);
+ if (last_week == (time_t) -1)
+ pr_crit("mktime(tm) returned (time_t) -1.");
+
+ return last_week;
+}
+
//static void
//cleanup_tmp(struct rpki_cache *cache, struct cache_node *node)
//{
struct cache_node *msm; /* Most Specific Match */
struct timespec now;
+ PR_DEBUG_MSG("Removing potentially abandoned %s", path);
+
/* XXX node->parent has to be set */
pm = find_msm(nftw_root, pstrdup(path), &msm);
if (!pm && !(msm->flags & CNF_RSYNC))
#include <sys/queue.h>
#include "alloc.c"
+#include "common.c"
//#include "json_util.c"
#include "mock.c"
#include "cache/cachent.c"
-#include "cache/common.c"
#include "cache/local_cache.c"
+#include "cache/util.c"
#include "data_structure/path_builder.c"
#include "types/str.c"
#include "types/url.c"
/* Mocks */
-static bool dl_error; /* Download should return error? */
+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;
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;
-static unsigned int rsync_counter; /* Times the rsync function was called */
-static unsigned int https_counter; /* Times the https function was called */
-
int
-file_exists(char const *file)
+file_exists(char const *path)
{
- struct downloaded_path *path;
- SLIST_FOREACH(path, &downloaded, hook)
- if (strcmp(file, path->path) == 0)
+ 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;
}
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;
}
struct downloaded_path *dl;
if (dl_error)
- return -EINVAL;
+ return dl_error;
if (file_exists(local) == 0)
return 0;
dl->path = pstrdup(local);
dl->visited = false;
SLIST_INSERT_HEAD(&downloaded, dl, hook);
+
+ if (dl_mock_type)
+ ck_assert_int_eq(0, mkdir_p(local, true));
+
return 0;
}
return error;
}
-MOCK_ABORT_INT(rrdp_update, struct cache_node *notif, struct cache_node *rpp)
+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)
/* Helpers */
static void
-setup_test(void)
+setup_test(bool dl_type)
{
- dl_error = false;
+ dl_error = 0;
+ dl_mock_type = dl_type;
SLIST_INIT(&downloaded);
ck_assert_int_eq(0, system("rm -rf tmp/"));
}
static void
-run_dl_rsync(char const *caRepository, char const *rpkiManifest,
- int expected_error, unsigned int expected_calls)
+run_dl_rsync(char const *caRepository, int expected_error,
+ unsigned int expected_calls)
{
static struct sia_uris sias;
sias.caRepository = pstrdup(caRepository);
sias.rpkiNotify = NULL;
- sias.rpkiManifest = pstrdup(rpkiManifest);
+ sias.rpkiManifest = NULL;
rsync_counter = 0;
https_counter = 0;
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)
{
struct downloaded_path *path;
+ PR_DEBUG_MSG("Checking %s", node->url);
+
path = find_downloaded_path(node);
if (node->tmpdir) {
if (path == NULL)
{
struct cache_node *echild, *achild, *tmp;
+ PR_DEBUG_MSG("Comparing %s", expected->url);
+
ck_assert_str_eq(expected->url, actual->url);
ck_assert_str_eq(expected->name, actual->name);
ck_assert_int_eq(expected->flags, actual->flags);
cachent_delete(https);
}
-//static void
-//new_iteration(bool outdate)
-//{
-// struct cache_node *node, *tmp;
-// time_t epoch;
-//
-// epoch = outdate ? get_days_ago(30) : get_days_ago(1);
-// HASH_ITER(hh, cache->ht, node, tmp)
-// node->attempt.ts = epoch;
-//}
-//
+static void
+ck_cache_rsync(struct cache_node *rsync)
+{
+ ck_cache(rsync, unode("https:", NULL));
+}
+
+static time_t epoch;
+
+static bool
+unfreshen(struct cache_node *node, char const *path)
+{
+ node->flags &= ~CNF_FRESH;
+ node->mtim = epoch;
+ return true;
+}
+
+static void
+new_iteration(bool outdate)
+{
+ epoch = outdate ? get_days_ago(30) : get_days_ago(1);
+ cachent_traverse(cache.rsync, unfreshen);
+}
+
//static void
//cache_reset(struct rpki_cache *cache)
//{
{
struct downloaded_path *path;
- dl_error = false;
+ dl_error = 0;
cache_commit();
while (!SLIST_EMPTY(&downloaded)) {
/* Tests */
-START_TEST(test_cache_download_rsync)
-{
- static const int SUCCESS = CNF_RSYNC | CNF_CACHED | CNF_FRESH | CNF_VALID;
-
- setup_test();
-
- run_dl_rsync("rsync://a.b.c/d", "rsync://a.b.c/d/mft", 0, 1);
- ck_cache(
- node("rsync:", 0, NULL,
- node("rsync://a.b.c", 0, NULL,
- node("rsync://a.b.c/d", SUCCESS, "tmp/tmp/0",
- node("rsync://a.b.c/d/mft", RSYNC_INHERIT, NULL, NULL),
- NULL),
- NULL),
- NULL),
- node("https:", 0, NULL, NULL));
-
- /* Redownload same file, nothing should happen */
- run_dl_rsync("rsync://a.b.c/d", "rsync://a.b.c/d/mft", 0, 0);
- ck_cache(
- node("rsync:", 0, NULL,
- node("rsync://a.b.c", 0, NULL,
- node("rsync://a.b.c/d", SUCCESS, "tmp/tmp/0",
- node("rsync://a.b.c/d/mft", RSYNC_INHERIT, NULL, NULL),
- NULL),
- NULL),
- NULL),
- node("https:", 0, NULL, NULL));
-
- /*
- * rsyncs are recursive, which means if we've been recently asked to
- * download d, we needn't bother redownloading d/e.
- */
- run_dl_rsync("rsync://a.b.c/d/e", "rsync://a.b.c/d/e/mft", 0, 0);
- ck_cache(
- node("rsync:", 0, NULL,
- node("rsync://a.b.c", 0, NULL,
- node("rsync://a.b.c/d", SUCCESS, "tmp/tmp/0",
- node("rsync://a.b.c/d/e", RSYNC_INHERIT, NULL,
- node("rsync://a.b.c/d/e/mft", RSYNC_INHERIT, NULL, NULL),
- NULL),
- node("rsync://a.b.c/d/mft", RSYNC_INHERIT, NULL, NULL),
- NULL),
- NULL),
- NULL),
- node("https:", 0, NULL, NULL));
-
- /*
- * rsyncs get truncated, because it results in much faster
- * synchronization in practice.
- * This is not defined in any RFCs; it's an effective standard,
- * and there would be consequences for violating it.
- */
- run_dl_rsync("rsync://x.y.z/m/n/o", "rsync://x.y.z/m/n/o/mft", 0, 1);
- ck_cache(
- node("rsync:", 0, NULL,
- node("rsync://a.b.c", 0, NULL,
- node("rsync://a.b.c/d", SUCCESS, "tmp/tmp/0",
- node("rsync://a.b.c/d/e", RSYNC_INHERIT, NULL,
- node("rsync://a.b.c/d/e/mft", RSYNC_INHERIT, NULL, NULL),
- NULL),
- node("rsync://a.b.c/d/mft", RSYNC_INHERIT, NULL, NULL),
- NULL),
- NULL),
- node("rsync://x.y.z", 0, NULL,
- node("rsync://x.y.z/m", SUCCESS, "tmp/tmp/1",
- node("rsync://x.y.z/m/n", RSYNC_INHERIT, NULL,
- node("rsync://x.y.z/m/n/o", RSYNC_INHERIT, NULL,
- node("rsync://x.y.z/m/n/o/mft", RSYNC_INHERIT, NULL, NULL),
- NULL),
- NULL),
- NULL),
- NULL),
- NULL),
- node("https:", 0, NULL, NULL));
-
-// /* Sibling */
-// run_dl_rsync("rsync://a.b.c/e/f", "rsync://a.b.c/e/f/mft", 0, 1);
-// ck_cache(
-// NODE("rsync://a.b.c/d/", 0, 1, true),
-// NODE("rsync://a.b.c/e/", 0, 1, true),
-// NODE("rsync://x.y.z/m/", 0, 1, true),
-// NULL);
-
- cleanup_test();
-}
-END_TEST
-
-//START_TEST(test_cache_download_rsync_error)
+static const int DOWNLOADED = CNF_RSYNC | CNF_CACHED | CNF_FRESH;
+static const int VALIDATED = RSYNC_INHERIT | CNF_VALID;
+static const int FULL = DOWNLOADED | VALIDATED;
+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();
+// setup_test(false);
//
-// dl_error = false;
-// run_cache_download("rsync://a.b.c/d", 0, 1, 0);
-// dl_error = true;
-// run_cache_download("rsync://a.b.c/e", -EINVAL, 1, 0);
-// ck_cache(
-// NODE("rsync://a.b.c/d/", 0, 1, true),
-// NODE("rsync://a.b.c/e/", -EINVAL, 0, false),
-// NULL);
+// 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));
//
-// /* Regardless of error, not reattempted because same iteration */
-// dl_error = true;
-// run_cache_download("rsync://a.b.c/e", -EINVAL, 0, 0);
-// ck_cache(
-// NODE("rsync://a.b.c/d/", 0, 1, true),
-// NODE("rsync://a.b.c/e/", -EINVAL, 0, false),
-// 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));
//
-// dl_error = false;
-// run_cache_download("rsync://a.b.c/e", -EINVAL, 0, 0);
-// ck_cache(
-// NODE("rsync://a.b.c/d/", 0, 1, true),
-// NODE("rsync://a.b.c/e/", -EINVAL, 0, false),
-// NULL);
-//
-// cleanup_test();
-//}
-//END_TEST
-//
-//START_TEST(test_cache_cleanup_rsync)
-//{
-// setup_test();
+// /*
+// * rsyncs are recursive, which means if we've been recently asked to
+// * download d, we needn't bother redownloading d/e.
+// */
+// 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));
//
// /*
-// * First iteration: Tree is created. No prunes, because nothing's
-// * outdated.
+// * rsyncs get truncated, because it results in much faster
+// * synchronization in practice.
+// * This is not defined in any RFCs; it's an effective standard,
+// * and there would be consequences for violating it.
// */
-// new_iteration(true);
-// run_cache_download("rsync://a.b.c/d", 0, 1, 0);
-// run_cache_download("rsync://a.b.c/e", 0, 1, 0);
-// cache_cleanup(cache);
-// ck_cache(
-// NODE("rsync://a.b.c/d/", 0, 1, true),
-// NODE("rsync://a.b.c/e/", 0, 1, true),
-// NULL);
+// 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));
//
-// /* One iteration with no changes, for paranoia */
-// new_iteration(true);
-// run_cache_download("rsync://a.b.c/d", 0, 1, 0);
-// run_cache_download("rsync://a.b.c/e", 0, 1, 0);
-// cache_cleanup(cache);
-// ck_cache(
-// NODE("rsync://a.b.c/d/", 0, 1, true),
-// NODE("rsync://a.b.c/e/", 0, 1, true),
-// 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));
//
-// /* Add one sibling */
-// new_iteration(true);
-// run_cache_download("rsync://a.b.c/d", 0, 1, 0);
-// run_cache_download("rsync://a.b.c/e", 0, 1, 0);
-// run_cache_download("rsync://a.b.c/f", 0, 1, 0);
-// cache_cleanup(cache);
-// ck_cache(
-// NODE("rsync://a.b.c/d/", 0, 1, true),
-// NODE("rsync://a.b.c/e/", 0, 1, true),
-// NODE("rsync://a.b.c/f/", 0, 1, true),
-// NULL);
+// cleanup_test();
+//}
+//END_TEST
//
-// /* Nodes don't get updated, but they're still too young. */
-// new_iteration(false);
-// cache_cleanup(cache);
-// ck_cache(
-// NODE("rsync://a.b.c/d/", 0, 1, true),
-// NODE("rsync://a.b.c/e/", 0, 1, true),
-// NODE("rsync://a.b.c/f/", 0, 1, true),
-// NULL);
+//START_TEST(test_cache_download_rsync_error)
+//{
+// setup_test(false);
+//
+// dl_error = 0;
+// run_dl_rsync("rsync://a.b.c/d", 0, 1);
+// 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));
//
-// /* Remove some branches */
-// new_iteration(true);
-// run_cache_download("rsync://a.b.c/d", 0, 1, 0);
-// cache_cleanup(cache);
-// ck_cache(NODE("rsync://a.b.c/d/", 0, 1, true), 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));
+//
+// 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));
//
+// cleanup_test();
+//}
+//END_TEST
+
+START_TEST(test_cache_cleanup_rsync)
+{
+ setup_test(true);
+
+ /*
+ * First iteration: Tree is created. No prunes, because nothing's
+ * outdated.
+ */
+ 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));
+
+ /* One iteration with no changes, for paranoia */
+ 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));
+
+ /* Add one sibling */
+ 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));
+
+ /* Nodes don't get updated, but they're still too young. */
+ 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));
+
+ /* 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));
+
// /* Remove old branch and add sibling at the same time */
// new_iteration(true);
-// run_cache_download("rsync://a.b.c/e", 0, 1, 0);
-// cache_cleanup(cache);
+// 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_cache_download("rsync://a.b.c/e/f/g", 0, 1, 0);
-// cache_cleanup(cache);
+// 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_cache_download("rsync://a.b.c/e", 0, 1, 0);
-// cache_cleanup(cache);
+// run_dl_rsync("rsync://a.b.c/e", 0, 1);
+// cleanup_cache();
// ck_cache(NODE("rsync://a.b.c/e/", 0, 1, true), NULL);
//
// /* Empty the tree */
// new_iteration(true);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NULL);
//
// /* Node exists, but file doesn't */
// new_iteration(true);
-// run_cache_download("rsync://a.b.c/e", 0, 1, 0);
-// run_cache_download("rsync://a.b.c/f", 0, 1, 0);
+// run_dl_rsync("rsync://a.b.c/e", 0, 1);
+// run_dl_rsync("rsync://a.b.c/f", 0, 1);
// ck_cache(
// NODE("rsync://a.b.c/e/", 0, 1, true),
// NODE("rsync://a.b.c/f/", 0, 1, true),
// NULL);
// ck_assert_int_eq(0, file_rm_rf("tmp/rsync/a.b.c/f"));
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NODE("rsync://a.b.c/e/", 0, 1, true), NULL);
-//
-// cleanup_test();
-//}
-//END_TEST
-//
+
+ cleanup_test();
+}
+END_TEST
+
//START_TEST(test_cache_cleanup_rsync_error)
//{
// setup_test();
//
// /* Set up */
// dl_error = false;
-// run_cache_download("rsync://a.b.c/d", 0, 1, 0);
+// run_dl_rsync("rsync://a.b.c/d", 0, 1);
// dl_error = true;
-// run_cache_download("rsync://a.b.c/e", -EINVAL, 1, 0);
+// run_dl_rsync("rsync://a.b.c/e", -EINVAL, 1);
// ck_cache(
// NODE("rsync://a.b.c/d/", 0, 1, true),
// NODE("rsync://a.b.c/e/", -EINVAL, 0, false),
// NULL);
//
// /* Node gets deleted because cached file doesn't exist */
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NODE("rsync://a.b.c/d/", 0, 1, true), NULL);
//
// /*
// */
// new_iteration(false);
// dl_error = true;
-// run_cache_download("rsync://a.b.c/d", -EINVAL, 1, 0);
+// run_dl_rsync("rsync://a.b.c/d", -EINVAL, 1);
// ck_cache(NODE("rsync://a.b.c/d/", -EINVAL, 1, true), NULL);
//
// /* Error is old; gets deleted */
// new_iteration(true);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NULL);
//
// cleanup_test();
// new_iteration(true);
// run_cache_download("https://a.b.c/d", 0, 0, 1);
// run_cache_download("https://a.b.c/e", 0, 0, 1);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(
// NODE("https://a.b.c/d", 0, 1, 1),
// NODE("https://a.b.c/e", 0, 1, 1),
// /* Remove one branch */
// new_iteration(true);
// run_cache_download("https://a.b.c/d", 0, 0, 1);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NODE("https://a.b.c/d", 0, 1, 1), NULL);
//
// /* Change the one branch */
// new_iteration(true);
// run_cache_download("https://a.b.c/e", 0, 0, 1);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NODE("https://a.b.c/e", 0, 1, 1), NULL);
//
// /* Add a child to the same branch, do not update the old one */
// new_iteration(true);
// run_cache_download("https://a.b.c/e/f/g", 0, 0, 1);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(
// NODE("https://a.b.c/e/f/g", 0, 1, 1), NULL);
//
// */
// new_iteration(true);
// run_cache_download("https://a.b.c/e/f", 0, 0, 1);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NODE("https://a.b.c/e/f", 0, 1, 1), NULL);
//
// /* Do it again. */
// new_iteration(true);
// run_cache_download("https://a.b.c/e", 0, 0, 1);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NODE("https://a.b.c/e", 0, 1, 1), NULL);
//
// /* Empty the tree */
// new_iteration(true);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NULL);
//
// /* Node exists, but file doesn't */
// NODE("https://a.b.c/f/g/h", 0, 1, 1),
// NULL);
// ck_assert_int_eq(0, file_rm_rf("tmp/https/a.b.c/f/g/h"));
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NODE("https://a.b.c/e", 0, 1, 1), NULL);
//
// cleanup_test();
// NULL);
//
// /* Deleted because file ENOENT. */
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(
// NODE("https://a.b.c/d", 0, 1, 1),
// NULL);
//
// /* Not deleted, because not old */
// new_iteration(false);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NODE("https://a.b.c/d", -EINVAL, 1, 1), NULL);
//
// /* Become old */
// new_iteration(true);
-// cache_cleanup(cache);
+// cleanup_cache();
// ck_cache(NULL);
//
// cleanup_test();
//}
//END_TEST
-
-START_TEST(test_dots)
-{
+//
+//START_TEST(test_dots)
+//{
// setup_test();
//
// run_cache_download("https://a.b.c/d", 0, 0, 1);
// NULL);
//
// cleanup_test();
-}
-END_TEST
-
+//}
+//END_TEST
+//
//START_TEST(test_tal_json)
//{
// json_t *json;
TCase *rsync, *https, *dot, *meta, *recover;
rsync = tcase_create("rsync");
- tcase_add_test(rsync, test_cache_download_rsync);
+// tcase_add_test(rsync, test_cache_download_rsync);
// tcase_add_test(rsync, test_cache_download_rsync_error);
-// tcase_add_test(rsync, test_cache_cleanup_rsync);
+ tcase_add_test(rsync, test_cache_cleanup_rsync);
// tcase_add_test(rsync, test_cache_cleanup_rsync_error);
https = tcase_create("https");
// tcase_add_test(https, test_cache_cleanup_https_error);
dot = tcase_create("dot");
- tcase_add_test(dot, test_dots);
+// tcase_add_test(dot, test_dots);
meta = tcase_create(TAL_METAFILE);
// tcase_add_test(meta, test_tal_json);