skip to content
==> tests/durable.c <==
1/* Writes are whole under their name (no .tmp left), links share the inode, a link whose source went is
2 * written instead, and directories sync. */
3#include "mesh/blobs/durable.h"
4#include "mesh/check.h"
5#include "mesh/strbuf.h"
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <sys/stat.h>
11#include <unistd.h>
12
13static char *slurp(const char *p, size_t *n) {
14    FILE *f = fopen(p, "rb");
15    if (!f) return NULL;
16    char *b = mxalloc(4096);
17    *n = fread(b, 1, 4096, f);
18    fclose(f);
19    return b;
20}
21
22int main(void) {
23    char *root = mfmt("%s/mesh-blobs-durable-%d", getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp", (int)getpid());
24    mb_remove_tree(root);
25    char *a = mfmt("%s/1.1", root), *b = mfmt("%s/2.1", root);
26    char *err = NULL;
27    CHECK(mb_make_durable(a, "h1", NULL, "pass sums", 9, &err));
28    CHECK(mb_sync_dir(a, &err));
29    char *pa = mfmt("%s/h1", a), *ta = mfmt("%s/h1.tmp", a);
30    size_t n;
31    char *got = slurp(pa, &n);
32    CHECK(got && n == 9 && memcmp(got, "pass sums", 9) == 0);
33    free(got);
34    struct stat st, st2;
35    CHECK(stat(ta, &st) != 0);
36    /* Another job's copy: a hard link, the same inode. */
37    CHECK(mb_make_durable(b, "h1", pa, "pass sums", 9, &err));
38    char *pb = mfmt("%s/h1", b);
39    CHECK(stat(pa, &st) == 0 && stat(pb, &st2) == 0 && st.st_ino == st2.st_ino);
40    /* Linking again over an existing name replaces it. */
41    CHECK(mb_make_durable(b, "h1", pa, "pass sums", 9, &err));
42    /* A link whose source went: the bytes are written. */
43    char *c = mfmt("%s/3.1", root);
44    CHECK(mb_make_durable(c, "h2", "/nonexistent/file", "late", 4, &err));
45    char *pc = mfmt("%s/h2", c);
46    got = slurp(pc, &n);
47    CHECK(got && n == 4 && memcmp(got, "late", 4) == 0);
48    free(got);
49    CHECK(!mb_sync_dir("/nonexistent/dir", &err));
50    CHECK(err && strstr(err, "/nonexistent/dir") != NULL);
51    free(err);
52    mb_remove_tree(root);
53    CHECK(stat(root, &st) != 0);
54    for (char *p[] = {root, a, b, pa, ta, pb, c, pc}, **q = p; q < p + 8; q++) free(*q);
55    return mesh_check_done();
56}