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

#include "test.h"
#include "key.h"
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

int main(void)
{
	char name[] = "key_gen_combopair_write() - generate and write keys to file";
	char fakehome[] = "0000-0009-XXXXXX";
	int rc;

	test_name(name);

	/* create fake home directory */
	if (!test_assert(mkdtemp(fakehome) != NULL, "mkdtemp()")) {
		perror("mkdtemp");
		return test_status;
	}
	/* generate keypair and write to disk */
	key_combo_t keyring;
	rc = key_gen_combopair_write(fakehome, &keyring);
	test_assert(rc == 0, "key_gen_combopair_write()");

	/* check directory path has been created */
	/* FAKEHOME/.config/lcagent/ */
	char *configpath;
	struct stat sb;
	rc = snprintf(NULL, 0, "%s/%s", fakehome, KEY_PATH);
	if (!test_assert(rc > 0, "calculate length of configpath")) {
		perror("snprintf");
		return test_status;
	}
	size_t len = (size_t)rc + 1;
	configpath = malloc(len);
	if (!test_assert(configpath != NULL, "allocate configpath")) return test_status;
	rc = snprintf(configpath, len, "%s/%s", fakehome, KEY_PATH);
	test_assert((size_t)rc == len - 1, "rc == len %zi/%zu", rc, len - 1);
	rc = stat(configpath, &sb);
	if (!test_assert(rc == 0, "stat '%s'", configpath)) goto err_free_configpath;
	if (!test_assert(chdir(configpath) == 0, "chdir %s", configpath)) goto err_free_configpath;

	/* check keyfile exists */
	rc = stat(keyring.phex, &sb);
	if (!test_assert(rc == 0, "stat '%s'", keyring.phex)) goto err_free_configpath;

	/* test file permissions */
	test_assert((sb.st_mode & ~S_IFMT) == (S_IRUSR|S_IWUSR), "file mode = %jo", sb.st_mode);

	/* verify secret key matches */
	char buf[KEY_SECRET_HEXLEN + 1];
	ssize_t byt;
	int fd = open(keyring.phex, O_RDONLY);
	test_assert(fd != -1, "open '%s'", keyring.phex);
	byt = read(fd, buf, sizeof buf);
	test_assert((size_t)byt == KEY_SECRET_HEXLEN, "%zi/%zu bytes read", byt, KEY_SECRET_HEXLEN);

	/* check default symlink */
	rc = stat("default", &sb);
	if (!test_assert(rc == 0, "default symlink created")) goto err_free_configpath;

err_free_configpath:
	free(configpath);
	return test_status;
}
