Add test/runner.c; Fix test failure due to allocating wrong size for linkmap; Overall cleanup;

This commit is contained in:
Nathan Fisher 2024-04-17 03:05:41 -04:00
parent a4fb6c7060
commit ebf8b1c901
7 changed files with 83 additions and 51 deletions

View file

@ -98,12 +98,11 @@ install_shared: libhaggis.so
test: libhaggis.a test: libhaggis.a
$(MAKE) -C test $(MAKE) -C test
testclean: testclean: clean
$(MAKE) -C test clean $(MAKE) -C test clean
clean: clean:
rm -rf *.a *.so *.o haggis rm -rf *.a *.so *.o haggis
$(MAKE) -C test clean
.PHONY: all bin shared static clean install install_include install_man \ .PHONY: all bin shared static clean install install_include install_man \
install_static install_shared testclean test install_static install_shared testclean test

View file

@ -5,10 +5,6 @@ libdir = $(DESTDIR)$(PREFIX)/lib
sharedir = $(DESTDIR)$(PREFIX)/share sharedir = $(DESTDIR)$(PREFIX)/share
mandir = $(sharedir)/man mandir = $(sharedir)/man
docdir = $(sharedir)/doc/haggis docdir = $(sharedir)/doc/haggis
# We need an `echo` program that doesn't screw with terminal escape sequences.
# This only matters if /bin/sh is a symlink to dash, as the echo builtin in dash
# will screw with them and pass them as printed characters.
ECHO = /bin/echo
# Comment this line if your OS ships libmd as part of libc # Comment this line if your OS ships libmd as part of libc
# (NetBSD, OpenBSD) # (NetBSD, OpenBSD)
LIBS += -lmd LIBS += -lmd

View file

@ -686,7 +686,6 @@ haggis_node *haggis_create_node(
msg = haggis_msg_init(NodeCreated, body); msg = haggis_msg_init(NodeCreated, body);
haggis_mq_push(mq, msg); haggis_mq_push(mq, msg);
} else if (S_ISREG(st.st_mode)) { } else if (S_ISREG(st.st_mode)) {
node->filetype.tag = normal;
res = haggis_init_file_node(node, &st, a, map, mq); res = haggis_init_file_node(node, &st, a, map, mq);
if (res != 0) if (res != 0)
return NULL; return NULL;

View file

@ -118,11 +118,8 @@ typedef struct {
#define HAGGIS_BUCKETS_BASE 64 #define HAGGIS_BUCKETS_BASE 64
typedef struct __bucket { typedef struct {
union { ino_t key;
ino_t val;
uint8_t bytes[sizeof(ino_t)];
} key;
uint64_t hash; uint64_t hash;
char *path; char *path;
} haggis_bucket; } haggis_bucket;

View file

@ -34,6 +34,7 @@
#include "haggis_private.h" #include "haggis_private.h"
#include <limits.h> // PATH_MAX #include <limits.h> // PATH_MAX
#include <stdio.h>
#include <stdlib.h> // calloc, free #include <stdlib.h> // calloc, free
#include <string.h> // strndup #include <string.h> // strndup
@ -69,7 +70,7 @@ haggis_linkmap* haggis_linkmap_init() {
map = calloc(1, sizeof(haggis_linkmap)); map = calloc(1, sizeof(haggis_linkmap));
if (map == NULL) if (map == NULL)
return NULL; return NULL;
map->buckets = calloc(HAGGIS_BUCKETS_BASE, sizeof(size_t)); map->buckets = calloc(HAGGIS_BUCKETS_BASE, sizeof(haggis_bucket));
if (map->buckets == NULL) { if (map->buckets == NULL) {
free(map); free(map);
return NULL; return NULL;
@ -86,7 +87,7 @@ void haggis_linkmap_deinit(haggis_linkmap *self) {
int haggis_linkmap_expand(haggis_linkmap *self) { int haggis_linkmap_expand(haggis_linkmap *self) {
haggis_bucket *buckets_new; haggis_bucket *buckets_new;
haggis_bucket *buckets_old; haggis_bucket *buckets_old;
size_t i, hash, idx; size_t i, idx;
buckets_new = calloc(self->capacity + HAGGIS_BUCKETS_BASE, sizeof(haggis_bucket)); buckets_new = calloc(self->capacity + HAGGIS_BUCKETS_BASE, sizeof(haggis_bucket));
if (buckets_new == NULL) if (buckets_new == NULL)
@ -95,10 +96,9 @@ int haggis_linkmap_expand(haggis_linkmap *self) {
self->buckets[i].path = NULL; self->buckets[i].path = NULL;
} }
for (i = 0; i < self->capacity; i++) { for (i = 0; i < self->capacity; i++) {
if (self->buckets[i].key.val != 0) { if (self->buckets[i].key != 0) {
hash = hash_fnv1a_64(&self->buckets[i].key.bytes[0], sizeof(ino_t));
self ->capacity += HAGGIS_BUCKETS_BASE; self ->capacity += HAGGIS_BUCKETS_BASE;
idx = self->capacity % hash; idx = self->capacity % self->buckets[i].hash;
buckets_new[idx] = self->buckets[i]; buckets_new[idx] = self->buckets[i];
} }
} }
@ -116,6 +116,7 @@ char* haggis_linkmap_get_or_add(haggis_linkmap *self, ino_t inode, char * path)
} key; } key;
char * target = NULL; char * target = NULL;
size_t idx, hash, i; size_t idx, hash, i;
haggis_bucket *bucket;
pthread_mutex_lock(&self->mutex); pthread_mutex_lock(&self->mutex);
if (self->len >= self->capacity) if (self->len >= self->capacity)
@ -124,14 +125,14 @@ char* haggis_linkmap_get_or_add(haggis_linkmap *self, ino_t inode, char * path)
hash = hash_fnv1a_64(key.bytes, sizeof(ino_t)); hash = hash_fnv1a_64(key.bytes, sizeof(ino_t));
idx = hash % self->capacity; idx = hash % self->capacity;
for (i = 0; i < self->capacity; i++) { for (i = 0; i < self->capacity; i++) {
if (self->buckets[idx].key.val == inode) { bucket = &self->buckets[idx];
target = strndup(self->buckets[idx].path, PATH_MAX - 1); if (bucket->key == inode) {
self->buckets[idx].path = path; target = strndup(bucket->path, PATH_MAX - 1);
break; break;
} else if (self->buckets[idx].key.val == 0) { } else if (bucket->key == 0) {
self->buckets[idx].key.val = inode; bucket->path = path;
self->buckets[idx].hash = hash; bucket->key = inode;
self->buckets[idx].path = path; bucket->hash = hash;
self->len++; self->len++;
break; break;
} else { } else {

View file

@ -1,5 +1,6 @@
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -9,51 +10,83 @@
#include "haggis.h" #include "haggis.h"
#include "mq.h" #include "mq.h"
int main() {
haggis_node *node0 = NULL, *node1 = NULL; haggis_node *node0 = NULL, *node1 = NULL;
haggis_linkmap *map = NULL; haggis_linkmap *map = NULL;
void log_and_die(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
if (map != NULL)
haggis_linkmap_deinit(map);
if (node0 != NULL)
haggis_node_deinit(node0);
if (node1 != NULL)
haggis_node_deinit(node1);
exit(EXIT_FAILURE);
}
int main() {
const char *orig = "Makefile";
const char *lnk = "output/Makefile";
haggis_mq mq; haggis_mq mq;
haggis_msg *msg; haggis_msg *msg;
char *orig = "Makefile";
char *lnk = "output/Makefile";
int ret = 0; int ret = 0;
map = haggis_linkmap_init(); map = haggis_linkmap_init();
assert(map != NULL); if (map == NULL)
log_and_die("OOM while creating linkmap\n");
if (haggis_mq_init(&mq)) if (haggis_mq_init(&mq))
return errno; return errno;
unlink(lnk); unlink(lnk);
ret = link(orig, lnk); ret = link(orig, lnk);
node0 = haggis_create_node(orig, sha256, map, &mq);
assert(node0 != NULL);
assert(node0->filetype.tag == normal);
assert(memcmp(node0->name.name, orig, 8) == 0);
if (ret) return ret; if (ret) return ret;
node1 = haggis_create_node(lnk, sha256, map, &mq); node0 = haggis_create_node("Makefile", sha256, map, &mq);
assert(node1 != NULL); if (node0 == NULL)
assert(node1->filetype.tag == hardlink); log_and_die("OOM while creating Node 0\n");
assert(memcmp(node1->name.name, lnk, 15) == 0); if (node0->filetype.tag != normal)
log_and_die("Node 0 incorrect tag: %i\n", node0->filetype.tag);
if (memcmp(node0->name.name, orig, 8) != 0)
log_and_die("Filename mismatch\n");
node1 = haggis_create_node("output/Makefile", sha256, map, &mq);
if (node1 == NULL)
log_and_die("OOM creating node1\n");
if (node1->filetype.tag != hardlink)
log_and_die("Node 1 incorrect tag: %u\n", node1->filetype.tag);
if (memcmp(node1->name.name, lnk, 15) != 0)
log_and_die("Node 1 incorrect filename\n");
ret = haggis_extract_node(node0, "output/extracted", &mq); ret = haggis_extract_node(node0, "output/extracted", &mq);
assert(ret == 0); if (ret)
log_and_die("Error extracting node0: %i\n", ret);
haggis_node_deinit(node0); haggis_node_deinit(node0);
ret = haggis_extract_node(node1, "output/extracted", &mq); ret = haggis_extract_node(node1, "output/extracted", &mq);
assert(ret == 0); if (ret)
log_and_die("Error extracting node1: %i\n", ret);
haggis_node_deinit(node1); haggis_node_deinit(node1);
msg = haggis_mq_pop(&mq); msg = haggis_mq_pop(&mq);
assert(msg->tag == NodeCreated); if (msg->tag != NodeCreated)
assert(memcmp(msg->body.f_name, orig, 8) == 0); log_and_die("Incorrect message, expected \"NodeCreated\", got %u\n", msg->tag);
if (memcmp(msg->body.f_name, orig, 9) != 0)
log_and_die("Filename mismatch: expected %s, got %s\n", orig, msg->body.f_name);
haggis_msg_deinit(msg); haggis_msg_deinit(msg);
msg = haggis_mq_pop(&mq); msg = haggis_mq_pop(&mq);
assert(msg->tag == NodeCreated); if (msg->tag != NodeCreated)
assert(memcmp(msg->body.f_name, lnk, 15) == 0); log_and_die("Incorrect message, expected \"NodeCreated\", got %u\n", msg->tag);
if (memcmp(msg->body.f_name, lnk, 15) != 0)
log_and_die("Filename mismatch: expected %s, got %s\n", orig, msg->body.f_name);
haggis_msg_deinit(msg); haggis_msg_deinit(msg);
msg = haggis_mq_pop(&mq); msg = haggis_mq_pop(&mq);
assert(msg->tag == NodeExtracted); if (msg->tag != NodeExtracted)
assert(memcmp(msg->body.f_name, orig, 8) == 0); log_and_die("Incorrect message, expected \"NodeExtracted\", got %u\n", msg->tag);
if (memcmp(msg->body.f_name, orig, 9) != 0)
log_and_die("Filename mismatch: expected %s, got %s\n", lnk, msg->body.f_name);
haggis_msg_deinit(msg); haggis_msg_deinit(msg);
msg = haggis_mq_pop(&mq); msg = haggis_mq_pop(&mq);
assert(msg->tag == NodeExtracted); if (msg->tag != NodeExtracted)
assert(memcmp(msg->body.f_name, lnk, 15) == 0); log_and_die("Incorrect message, expected \"NodeExtracted\", got %u\n", msg->tag);
if (memcmp(msg->body.f_name, lnk, 15) != 0)
log_and_die("Filename mismatch: expected %s, got %s\n", orig, msg->body.f_name);
haggis_msg_deinit(msg); haggis_msg_deinit(msg);
haggis_linkmap_deinit(map); haggis_linkmap_deinit(map);
return 0; return 0;

View file

@ -2,17 +2,24 @@
#include <stdlib.h> #include <stdlib.h>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int i, pass = 0, fail = 0, skip = 0, total, ret; int i, pass = 0, fail = 0, skip = 0, total, ret, read = 0;
FILE *pipe; FILE *pipe;
char cmd[100]; char cmd[100], output[500];
total = argc-1; total = argc-1;
printf("\n\t=== \033[0;33mRunning %i tests\033[0m ===\n", total); printf("\n\t=== \033[0;33mRunning %i tests\033[0m ===\n", total);
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
snprintf(cmd, 100, "./%s", argv[i]); snprintf(cmd, 100, "./%s", argv[i]);
printf("%-25s", argv[i]); printf("%-25s", argv[i]);
pipe = popen(cmd, "r"); pipe = popen(cmd, "w");
read = fread(&output, 1, 500, pipe);
ret = pclose(pipe); ret = pclose(pipe);
if (read) {
fail++;
printf("\033[0;31mFailed\033[0m\n");
fprintf(stderr, "%s\n", &output);
continue;
}
switch (WEXITSTATUS(ret)) { switch (WEXITSTATUS(ret)) {
case 0: case 0:
pass++; pass++;