/* SPDX-License-Identifier: GPL-2.0 */
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/zalloc.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <subcmd/exec-cmd.h>
#include <subcmd/parse-options.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <api/io.h>
#include "builtin.h"
#include "tests-scripts.h"
#include "color.h"
#include "debug.h"
#include "hist.h"
#include "intlist.h"
#include "string2.h"
#include "symbol.h"
#include "tests.h"
#include "util/rlimit.h"
#include "util/util.h"

static int shell_tests__dir_fd(void)
{
	char path[PATH_MAX], *exec_path;
	static const char * const devel_dirs[] = { "./tools/perf/tests/shell", "./tests/shell", };

	for (size_t i = 0; i < ARRAY_SIZE(devel_dirs); ++i) {
		int fd = open(devel_dirs[i], O_PATH);

		if (fd >= 0)
			return fd;
	}

	/* Then installed path. */
	exec_path = get_argv_exec_path();
	scnprintf(path, sizeof(path), "%s/tests/shell", exec_path);
	free(exec_path);
	return open(path, O_PATH);
}

static char *shell_test__description(int dir_fd, const char *name)
{
	struct io io;
	char buf[128], desc[256];
	int ch, pos = 0;

	io__init(&io, openat(dir_fd, name, O_RDONLY), buf, sizeof(buf));
	if (io.fd < 0)
		return NULL;

	/* Skip first line - should be #!/bin/sh Shebang */
	if (io__get_char(&io) != '#')
		goto err_out;
	if (io__get_char(&io) != '!')
		goto err_out;
	do {
		ch = io__get_char(&io);
		if (ch < 0)
			goto err_out;
	} while (ch != '\n');

	do {
		ch = io__get_char(&io);
		if (ch < 0)
			goto err_out;
	} while (ch == '#' || isspace(ch));
	while (ch > 0 && ch != '\n') {
		desc[pos++] = ch;
		if (pos >= (int)sizeof(desc) - 1)
			break;
		ch = io__get_char(&io);
	}
	while (pos > 0 && isspace(desc[--pos]))
		;
	desc[++pos] = '\0';
	close(io.fd);
	return strdup(desc);
err_out:
	close(io.fd);
	return NULL;
}

/* Is this full file path a shell script */
static bool is_shell_script(int dir_fd, const char *path)
{
	const char *ext;

	ext = strrchr(path, '.');
	if (!ext)
		return false;
	if (!strcmp(ext, ".sh")) { /* Has .sh extension */
		if (faccessat(dir_fd, path, R_OK | X_OK, 0) == 0) /* Is executable */
			return true;
	}
	return false;
}

/* Is this file in this dir a shell script (for test purposes) */
static bool is_test_script(int dir_fd, const char *name)
{
	return is_shell_script(dir_fd, name);
}

/* Duplicate a string and fall over and die if we run out of memory */
static char *strdup_check(const char *str)
{
	char *newstr;

	newstr = strdup(str);
	if (!newstr) {
		pr_err("Out of memory while duplicating test script string\n");
		abort();
	}
	return newstr;
}

static int shell_test__run(struct test_suite *test, int subtest __maybe_unused)
{
	const char *file = test->priv;
	int err;
	char *cmd = NULL;

	if (asprintf(&cmd, "%s%s", file, verbose ? " -v" : "") < 0)
		return TEST_FAIL;
	err = system(cmd);
	free(cmd);
	if (!err)
		return TEST_OK;

	return WEXITSTATUS(err) == 2 ? TEST_SKIP : TEST_FAIL;
}

static void append_script(int dir_fd, const char *name, char *desc,
			  struct test_suite ***result,
			  size_t *result_sz)
{
	char filename[PATH_MAX], link[128];
	struct test_suite *test_suite, **result_tmp;
	struct test_case *tests;
	size_t len;

	snprintf(link, sizeof(link), "/proc/%d/fd/%d", getpid(), dir_fd);
	len = readlink(link, filename, sizeof(filename));
	if (len < 0) {
		pr_err("Failed to readlink %s", link);
		return;
	}
	filename[len++] = '/';
	strcpy(&filename[len], name);

	tests = calloc(2, sizeof(*tests));
	if (!tests) {
		pr_err("Out of memory while building script test suite list\n");
		return;
	}
	tests[0].name = strdup_check(name);
	tests[0].desc = strdup_check(desc);
	tests[0].run_case = shell_test__run;

	test_suite = zalloc(sizeof(*test_suite));
	if (!test_suite) {
		pr_err("Out of memory while building script test suite list\n");
		free(tests);
		return;
	}
	test_suite->desc = desc;
	test_suite->test_cases = tests;
	test_suite->priv = strdup_check(filename);
	/* Realloc is good enough, though we could realloc by chunks, not that
	 * anyone will ever measure performance here */
	result_tmp = realloc(*result, (*result_sz + 1) * sizeof(*result_tmp));
	if (result_tmp == NULL) {
		pr_err("Out of memory while building script test suite list\n");
		free(tests);
		free(test_suite);
		return;
	}
	/* Add file to end and NULL terminate the struct array */
	*result = result_tmp;
	(*result)[*result_sz] = test_suite;
	(*result_sz)++;
}

static void append_scripts_in_dir(int dir_fd,
				  struct test_suite ***result,
				  size_t *result_sz)
{
	struct dirent **entlist;
	struct dirent *ent;
	int n_dirs, i;

	/* List files, sorted by alpha */
	n_dirs = scandirat(dir_fd, ".", &entlist, NULL, alphasort);
	if (n_dirs == -1)
		return;
	for (i = 0; i < n_dirs && (ent = entlist[i]); i++) {
		int fd;

		if (ent->d_name[0] == '.')
			continue; /* Skip hidden files */
		if (is_test_script(dir_fd, ent->d_name)) { /* It's a test */
			char *desc = shell_test__description(dir_fd, ent->d_name);

			if (desc) /* It has a desc line - valid script */
				append_script(dir_fd, ent->d_name, desc, result, result_sz);
			continue;
		}
		if (ent->d_type != DT_DIR) {
			struct stat st;

			if (ent->d_type != DT_UNKNOWN)
				continue;
			fstatat(dir_fd, ent->d_name, &st, 0);
			if (!S_ISDIR(st.st_mode))
				continue;
		}
		fd = openat(dir_fd, ent->d_name, O_PATH);
		append_scripts_in_dir(fd, result, result_sz);
	}
	for (i = 0; i < n_dirs; i++) /* Clean up */
		zfree(&entlist[i]);
	free(entlist);
}

struct test_suite **create_script_test_suites(void)
{
	struct test_suite **result = NULL, **result_tmp;
	size_t result_sz = 0;
	int dir_fd = shell_tests__dir_fd(); /* Walk  dir */

	/*
	 * Append scripts if fd is good, otherwise return a NULL terminated zero
	 * length array.
	 */
	if (dir_fd >= 0)
		append_scripts_in_dir(dir_fd, &result, &result_sz);

	result_tmp = realloc(result, (result_sz + 1) * sizeof(*result_tmp));
	if (result_tmp == NULL) {
		pr_err("Out of memory while building script test suite list\n");
		abort();
	}
	/* NULL terminate the test suite array. */
	result = result_tmp;
	result[result_sz] = NULL;
	if (dir_fd >= 0)
		close(dir_fd);
	return result;
}
