/*
 * Copyright (c) 2020 Nordic Semiconductor
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief Test logging to file system
 *
 */

#include <stdbool.h>
#include <stdlib.h>
#include <zephyr.h>
#include <ztest.h>
#include <fs/fs.h>

#define DT_DRV_COMPAT zephyr_fstab_littlefs
#define TEST_AUTOMOUNT DT_PROP(DT_DRV_INST(0), automount)
#if !TEST_AUTOMOUNT
#include <fs/littlefs.h>
#define PARTITION_NODE DT_NODELABEL(lfs1)
FS_FSTAB_DECLARE_ENTRY(PARTITION_NODE);
#endif

#define MAX_PATH_LEN (256 + 7)

static const char *log_prefix = CONFIG_LOG_BACKEND_FS_FILE_PREFIX;

int write_log_to_file(uint8_t *data, size_t length, void *ctx);


static void test_fs_nonexist(void)
{
	#if TEST_AUTOMOUNT
	ztest_test_skip();
	#else
	uint8_t to_log[] = "Log to left behind";
	int rc;

	rc = write_log_to_file(to_log, sizeof(to_log), NULL);
	zassert_equal(rc, sizeof(to_log), "Unexpected rteval.");
	struct fs_mount_t *mp = &FS_FSTAB_ENTRY(PARTITION_NODE);

	rc = fs_mount(mp);
	zassert_equal(rc, 0, "Can not mount FS.");
	#endif
}

static void test_wipe_fs_logs(void)
{
	int rc;
	struct fs_dir_t dir;
	struct fs_file_t file;
	char fname[MAX_PATH_LEN];

	fs_dir_t_init(&dir);
	fs_file_t_init(&file);

	rc = fs_opendir(&dir, CONFIG_LOG_BACKEND_FS_DIR);
	if (rc) {
		/* log directory might not exist jet */
		return;
	}

	/* Iterate over logging directory. */
	while (1) {
		struct fs_dirent ent = { 0 };

		rc = fs_readdir(&dir, &ent);
		zassert_equal(rc, 0, "Can not read directory.");
		if ((rc < 0) || (ent.name[0] == 0)) {
			break;
		}
		if (ent.type == FS_DIR_ENTRY_FILE &&
		    strncmp(ent.name, log_prefix, strlen(log_prefix)) == 0) {
			sprintf(fname, "%s/%s", CONFIG_LOG_BACKEND_FS_DIR,
				ent.name);
			rc = fs_unlink(fname);
			zassert_equal(rc, 0, "Can not remove file %s.", fname);
			TC_PRINT("removed: %s\n", fname);
		}
	}

	(void)fs_closedir(&dir);
}

static void test_log_fs_file_content(void)
{
	int rc;
	struct fs_file_t file;
	char log_read[MAX_PATH_LEN];
	uint8_t to_log[] = "Corect Log 1";
	static char fname[MAX_PATH_LEN];

	fs_file_t_init(&file);

	rc = write_log_to_file(to_log, sizeof(to_log), NULL);

	sprintf(fname, "%s/%s0000", CONFIG_LOG_BACKEND_FS_DIR, log_prefix);

	zassert_equal(fs_open(&file, fname, FS_O_READ), 0,
		      "Can not open log file.");

	zassert_true(fs_read(&file, log_read, MAX_PATH_LEN) >= 0,
		     "Can not read log file.");

	rc = strncmp(log_read, to_log, sizeof(log_read));
	zassert_equal(rc, 0, "Text inside log file is not correct.");

	zassert_equal(fs_close(&file), 0, "Can not close log file.");

	to_log[sizeof(to_log)-2] = '2';
	rc = write_log_to_file(to_log, sizeof(to_log), NULL);

	zassert_equal(fs_open(&file, fname, FS_O_READ), 0,
		      "Can not open log file.");

	zassert_equal(fs_seek(&file, sizeof(to_log), FS_SEEK_SET), 0,
		      "Bad file size");

	zassert_true(fs_read(&file, log_read, MAX_PATH_LEN) >= 0,
		     "Can not read log file.");

	rc = strncmp(log_read, to_log, sizeof(log_read));
	zassert_equal(rc, 0, "Text inside log file is not correct.");

	zassert_equal(fs_close(&file), 0, "Can not close log file.");
}

static void test_log_fs_file_size(void)
{
	int rc;
	int i;
	struct fs_dir_t dir;
	int file_ctr = 0;
	static char fname[MAX_PATH_LEN];
	uint8_t to_log[] = "Text Log";
	struct fs_dirent entry;

	fs_dir_t_init(&dir);

	sprintf(fname, "%s/%s0000", CONFIG_LOG_BACKEND_FS_DIR, log_prefix);
	zassert_equal(fs_stat(fname, &entry), 0, "Can not get file info.");

	/* Fill in log file over size limit. */
	for (i = 0;
	     i <= (CONFIG_LOG_BACKEND_FS_FILE_SIZE - entry.size) /
		  sizeof(to_log);
	     i++) {
		rc = write_log_to_file(to_log, sizeof(to_log), NULL);
		/* Written length not tracked here. */
		ARG_UNUSED(rc);
	}

	zassert_equal(fs_stat(fname, &entry), 0, "Can not get file info.");
	size_t exp_size = CONFIG_LOG_BACKEND_FS_FILE_SIZE -
			  (CONFIG_LOG_BACKEND_FS_FILE_SIZE - entry.size) %
			  sizeof(to_log);
	zassert_equal(entry.size, exp_size, "Unexpected %s file size (%d B)",
		      fname, entry.size);

	sprintf(fname, "%s/%s0001", CONFIG_LOG_BACKEND_FS_DIR, log_prefix);
	zassert_equal(fs_stat(fname, &entry), 0, "Can not get file info.");

	zassert_equal(entry.size, sizeof(to_log),
		      "Unexpected %s file size (%d B)",
		      fname, entry.size);

	rc = fs_opendir(&dir, CONFIG_LOG_BACKEND_FS_DIR);
	zassert_equal(rc, 0, "Can not open directory.");
	/* Count number of log files. */
	while (rc >= 0) {
		struct fs_dirent ent = { 0 };

		rc = fs_readdir(&dir, &ent);
		if ((rc < 0) || (ent.name[0] == 0)) {
			break;
		}
		if (strstr(ent.name, log_prefix) != NULL) {
			++file_ctr;
		}
	}
	(void)fs_closedir(&dir);
	zassert_equal(file_ctr, 2, "File changing failed");
}

static void test_log_fs_files_max(void)
{
	int rc;
	int i;
	struct fs_dir_t dir;
	int file_ctr = 0;
	uint8_t to_log[] = "Text Log";
	struct fs_dirent ent;
	uint32_t test_mask = 0;

	fs_dir_t_init(&dir);

	/* Fill in log files over files count limit. */
	for (i = 0;
	     i <= CONFIG_LOG_BACKEND_FS_FILE_SIZE /
		  sizeof(to_log) * (CONFIG_LOG_BACKEND_FS_FILES_LIMIT - 1);
	     i++) {
		rc = write_log_to_file(to_log, sizeof(to_log), NULL);
		/* Written length not tracked here. */
		ARG_UNUSED(rc);
	}

	rc = fs_opendir(&dir, CONFIG_LOG_BACKEND_FS_DIR);
	zassert_equal(rc, 0, "Can not open directory.");
	/* Count log files. */
	while (rc >= 0) {

		rc = fs_readdir(&dir, &ent);
		if ((rc < 0) || (ent.name[0] == 0)) {
			break;
		}
		if (strstr(ent.name, log_prefix) != NULL) {
			++file_ctr;
			test_mask |= 1 << atoi(&ent.name[strlen(log_prefix)]);
		}
	}
	(void)fs_closedir(&dir);
	zassert_equal(file_ctr, CONFIG_LOG_BACKEND_FS_FILES_LIMIT,
		      "Bad files count: expected %d, got %d ",
		      CONFIG_LOG_BACKEND_FS_FILES_LIMIT, file_ctr);
	/*expected files: log.0001, log.0002, log.0003, log.0004 */
	zassert_equal(test_mask, 0b11110, "Unexpected file numeration");
}

/* Test case main entry. */
void test_main(void)
{
	ztest_test_suite(test_log_backend_fs,
			 ztest_unit_test(test_fs_nonexist),
			 ztest_unit_test(test_wipe_fs_logs),
			 ztest_unit_test(test_log_fs_file_content),
			 ztest_unit_test(test_log_fs_file_size),
			 ztest_unit_test(test_log_fs_files_max));
	ztest_run_test_suite(test_log_backend_fs);
}
