/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* Copyright (c) 2023 Brett Sheffield <bacs@librecast.net> */

#include "test.h"
#include "testdata.h"
#include <librecast/mdex.h>
#include <librecast.h>
#include <librecast/crypto.h>

int main(void)
{
	unsigned char hash[HASHSIZE];
	unsigned char alias[HASHSIZE];
	mdex_t *mdex;
	mdex_entry_t entry = {0};
	const size_t entries = 64;
	size_t z;
	int rc;

	test_name("mdex_get() find aliased entry");

	/* create index and some entries */
	mdex = mdex_init(entries);
	entry.type = MDEX_PTR;
	for (size_t i = 0; i < entries; i++) {
		hash_generic(hash, sizeof hash, (unsigned char *)&i, sizeof i);
		entry.ptr.size = sizeof i;
		entry.ptr.data = (void *)i;
		rc = mdex_put(mdex, hash, sizeof hash, &entry);
		test_assert(rc == 0, "mdex_put() returned %i (entry %i)", rc, i);
	}

	/* try to fetch entry that doesn't exist */
	rc = entries + 1;
	hash_generic(hash, sizeof hash, (unsigned char *)&rc, sizeof rc);
	rc = mdex_get(mdex, hash, sizeof hash, &entry);
	test_assert(rc == -1, "mdex_get() returned %i (entry doesn't exist)");
	test_assert(errno == ENOENT, "try to fetch entry that doesn't exist");

	/* verify the entries we did write are correct */
	for (size_t i = 0; i < entries; i++) {
		hash_generic(hash, sizeof hash, (unsigned char *)&i, sizeof i);
		memset(&entry, 0, sizeof entry);
		rc = mdex_get(mdex, hash, sizeof hash, &entry);
		test_assert(rc == 0, "mdex_get() returned %i (entry %i)", rc, i);
		test_assert((size_t)entry.ptr.data == i, "data matches (%i)", i);
	}

	/* write an alias entry (65), pointing to entry 42 */
	z = entries + 1;
	hash_generic(hash, sizeof hash, (unsigned char *)&z, sizeof z);
	z = 42;
	hash_generic(alias, sizeof alias, (unsigned char *)&z, sizeof z);
	rc = mdex_alias(mdex, hash, sizeof hash, alias, sizeof alias);
	test_assert(rc == 0, "mdex_alias() returned %i", rc);
	perror("mdex_alias");

	memset(&entry, 0, sizeof entry);
	rc = mdex_get(mdex, hash, sizeof hash, &entry);
	test_assert(rc == 0, "mdex_get() returned %i (fetching alias)", rc);

	/* alias entry retrieved should be that of the entry it points to */
	test_assert(entry.ptr.size == sizeof(size_t), "entry size correct");
	test_assert((size_t)entry.ptr.data == 42, "alias fetched correct entry");

	mdex_free(mdex);
	return test_status;
}
