/*
 * Copyright (c) 2019 Peter Bigot Consulting, LLC
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/* littlefs performance testing */

#include <string.h>
#include <stdlib.h>
#include <kernel.h>
#include <ztest.h>
#include "testfs_tests.h"
#include "testfs_lfs.h"
#include <lfs.h>

#include <fs/littlefs.h>

#define HELLO "hello"
#define GOODBYE "goodbye"

static int write_read(const char *tag,
		      struct fs_mount_t *mp,
		      size_t buf_size,
		      size_t nbuf)
{
	const struct lfs_config *lcp = &((const struct fs_littlefs *)mp->fs_data)->cfg;
	struct testfs_path path;
	struct fs_statvfs vfs;
	struct fs_dirent stat;
	struct fs_file_t file;
	size_t total = nbuf * buf_size;
	uint32_t t0;
	uint32_t t1;
	uint8_t *buf;
	int rc;
	int rv = TC_FAIL;

	fs_file_t_init(&file);
	TC_PRINT("clearing %s for %s write/read test\n",
		 mp->mnt_point, tag);
	if (testfs_lfs_wipe_partition(mp) != TC_PASS) {
		return TC_FAIL;
	}

	rc = fs_mount(mp);
	if (rc != 0) {
		TC_PRINT("Mount %s failed: %d\n", mp->mnt_point, rc);
		return TC_FAIL;
	}

	rc = fs_statvfs(mp->mnt_point, &vfs);
	if (rc != 0) {
		TC_PRINT("statvfs %s failed: %d\n", mp->mnt_point, rc);
		goto out_mnt;
	}

	TC_PRINT("%s: bsize %lu ; frsize %lu ; blocks %lu ; bfree %lu\n",
		 mp->mnt_point,
		 vfs.f_bsize, vfs.f_frsize, vfs.f_blocks, vfs.f_bfree);
	TC_PRINT("read_size %u ; prog_size %u ; cache_size %u ; lookahead_size %u\n",
		 lcp->read_size, lcp->prog_size, lcp->cache_size, lcp->lookahead_size);

	testfs_path_init(&path, mp,
			 "data",
			 TESTFS_PATH_END);

	buf = calloc(buf_size, sizeof(uint8_t));
	if (buf == NULL) {
		TC_PRINT("Failed to allocate %zu-byte buffer\n", buf_size);
		goto out_mnt;
	}

	for (size_t i = 0; i < buf_size; ++i) {
		buf[i] = i;
	}

	TC_PRINT("creating and writing %zu %zu-byte blocks\n",
		 nbuf, buf_size);

	rc = fs_open(&file, path.path, FS_O_CREATE | FS_O_RDWR);
	if (rc != 0) {
		TC_PRINT("Failed to open %s for write: %d\n", path.path, rc);
		goto out_buf;
	}

	t0 = k_uptime_get_32();
	for (size_t i = 0; i < nbuf; ++i) {
		rc = fs_write(&file, buf, buf_size);
		if (buf_size != rc) {
			TC_PRINT("Failed to write buf %zu: %d\n", i, rc);
			goto out_file;
		}
	}
	t1 = k_uptime_get_32();

	if (t1 == t0) {
		t1++;
	}

	(void)fs_close(&file);

	rc = fs_stat(path.path, &stat);
	if (rc != 0) {
		TC_PRINT("Failed to stat %s: %d\n", path.path, rc);
		goto out_buf;
	}

	if (stat.size != total) {
		TC_PRINT("File size %zu not %zu\n", stat.size, total);
		goto out_buf;
	}

	TC_PRINT("%s write %zu * %zu = %zu bytes in %u ms: "
		 "%u By/s, %u KiBy/s\n",
		 tag, nbuf, buf_size, total, (t1 - t0),
		 (uint32_t)(total * 1000U / (t1 - t0)),
		 (uint32_t)(total * 1000U / (t1 - t0) / 1024U));

	rc = fs_open(&file, path.path, FS_O_CREATE | FS_O_RDWR);
	if (rc != 0) {
		TC_PRINT("Failed to open %s for write: %d\n", path.path, rc);
		goto out_buf;
	}

	t0 = k_uptime_get_32();
	for (size_t i = 0; i < nbuf; ++i) {
		rc = fs_read(&file, buf, buf_size);
		if (buf_size != rc) {
			TC_PRINT("Failed to read buf %zu: %d\n", i, rc);
			goto out_file;
		}
	}
	t1 = k_uptime_get_32();

	if (t1 == t0) {
		t1++;
	}

	TC_PRINT("%s read %zu * %zu = %zu bytes in %u ms: "
		 "%u By/s, %u KiBy/s\n",
		 tag, nbuf, buf_size, total, (t1 - t0),
		 (uint32_t)(total * 1000U / (t1 - t0)),
		 (uint32_t)(total * 1000U / (t1 - t0) / 1024U));

	rv = TC_PASS;

out_file:
	(void)fs_close(&file);

out_buf:
	free(buf);

out_mnt:
	(void)fs_unmount(mp);

	return rv;
}

static int custom_write_test(const char *tag,
			     const struct fs_mount_t *mp,
			     const struct lfs_config *cfgp,
			     size_t buf_size,
			     size_t nbuf)
{
	struct fs_littlefs data = {
		.cfg = *cfgp,
	};
	struct fs_mount_t lfs_mnt = {
		.type = FS_LITTLEFS,
		.fs_data = &data,
		.storage_dev = mp->storage_dev,
		.mnt_point = mp->mnt_point,
	};
	struct lfs_config *lcp = &data.cfg;
	int rv = TC_FAIL;

	if (lcp->cache_size == 0) {
		lcp->cache_size = CONFIG_FS_LITTLEFS_CACHE_SIZE;
	}
	if (lcp->lookahead_size == 0) {
		lcp->lookahead_size = CONFIG_FS_LITTLEFS_LOOKAHEAD_SIZE;
	}

	lcp->read_buffer = malloc(lcp->cache_size);
	lcp->prog_buffer = malloc(lcp->cache_size);
	lcp->lookahead_buffer = malloc(lcp->lookahead_size);

	TC_PRINT("bufs %p %p %p\n", lcp->read_buffer, lcp->prog_buffer, lcp->lookahead_buffer);

	if ((lcp->read_buffer == NULL)
	    || (lcp->prog_buffer == NULL)
	    || (lcp->lookahead_buffer == NULL)) {
		TC_PRINT("%s buffer allocation failed\n", tag);
		goto out_free;
	}

	rv = write_read(tag, &lfs_mnt, buf_size, nbuf);

out_free:
	if (lcp->read_buffer) {
		free(lcp->read_buffer);
	}
	if (lcp->prog_buffer) {
		free(lcp->prog_buffer);
	}
	if (lcp->lookahead_buffer) {
		free(lcp->lookahead_buffer);
	}

	return rv;
}

static int small_8_1K_cust(void)
{
	struct lfs_config cfg = {
		.read_size = LARGE_IO_SIZE,
		.prog_size = LARGE_IO_SIZE,
		.cache_size = LARGE_CACHE_SIZE,
		.lookahead_size = LARGE_LOOKAHEAD_SIZE
	};

	return custom_write_test("small 8x1K bigfile", &testfs_small_mnt, &cfg, 1024, 8);
}

void test_lfs_perf(void)
{
	k_sleep(K_MSEC(100));   /* flush log messages */
	zassert_equal(write_read("small 8x1K dflt",
				 &testfs_small_mnt,
				 1024, 8),
		      TC_PASS,
		      "failed");

	if (IS_ENABLED(CONFIG_APP_TEST_CUSTOM)) {
		k_sleep(K_MSEC(100));   /* flush log messages */
		zassert_equal(small_8_1K_cust(), TC_PASS,
			      "failed");

		k_sleep(K_MSEC(100));   /* flush log messages */
		zassert_equal(write_read("medium 32x2K dflt",
					 &testfs_medium_mnt,
					 2048, 32),
			      TC_PASS,
			      "failed");

		k_sleep(K_MSEC(100));   /* flush log messages */
		zassert_equal(write_read("large 64x4K dflt",
					 &testfs_large_mnt,
					 4096, 64),
			      TC_PASS,
			      "failed");
	}
}
