// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2020, Oracle and/or its affiliates.
 *    Author: Alan Maguire <alan.maguire@oracle.com>
 */

#include <linux/debugfs.h>
#include <linux/module.h>

#include <kunit/test.h>
#include <kunit/test-bug.h>

#include "string-stream.h"
#include "debugfs.h"

#define KUNIT_DEBUGFS_ROOT             "kunit"
#define KUNIT_DEBUGFS_RESULTS          "results"
#define KUNIT_DEBUGFS_RUN              "run"

/*
 * Create a debugfs representation of test suites:
 *
 * Path						Semantics
 * /sys/kernel/debug/kunit/<testsuite>/results	Show results of last run for
 *						testsuite
 * /sys/kernel/debug/kunit/<testsuite>/run	Write to this file to trigger
 *						testsuite to run
 *
 */

static struct dentry *debugfs_rootdir;

void kunit_debugfs_cleanup(void)
{
	debugfs_remove_recursive(debugfs_rootdir);
}

void kunit_debugfs_init(void)
{
	if (!debugfs_rootdir)
		debugfs_rootdir = debugfs_create_dir(KUNIT_DEBUGFS_ROOT, NULL);
}

static void debugfs_print_result(struct seq_file *seq, struct string_stream *log)
{
	struct string_stream_fragment *frag_container;

	if (!log)
		return;

	/*
	 * Walk the fragments so we don't need to allocate a temporary
	 * buffer to hold the entire string.
	 */
	spin_lock(&log->lock);
	list_for_each_entry(frag_container, &log->fragments, node)
		seq_printf(seq, "%s", frag_container->fragment);
	spin_unlock(&log->lock);
}

/*
 * /sys/kernel/debug/kunit/<testsuite>/results shows all results for testsuite.
 */
static int debugfs_print_results(struct seq_file *seq, void *v)
{
	struct kunit_suite *suite = (struct kunit_suite *)seq->private;
	enum kunit_status success;
	struct kunit_case *test_case;

	if (!suite)
		return 0;

	success = kunit_suite_has_succeeded(suite);

	/* Print KTAP header so the debugfs log can be parsed as valid KTAP. */
	seq_puts(seq, "KTAP version 1\n");
	seq_puts(seq, "1..1\n");

	if (suite->status != KUNIT_SKIPPED) {
		/* Print suite header because it is not stored in the test logs. */
		seq_puts(seq,
			 KUNIT_SUBTEST_INDENT "KTAP version 1\n");
		seq_printf(seq,
			   KUNIT_SUBTEST_INDENT "# Subtest: %s\n",
			   suite->name);
		seq_printf(seq,
			   KUNIT_SUBTEST_INDENT "1..%zd\n",
			   kunit_suite_num_test_cases(suite));

		kunit_suite_for_each_test_case(suite, test_case)
			debugfs_print_result(seq, test_case->log);
	}

	debugfs_print_result(seq, suite->log);

	if (suite->status != KUNIT_SKIPPED)
		seq_printf(seq, "%s %d %s\n",
			   kunit_status_to_ok_not_ok(success), 1, suite->name);
	else
		seq_printf(seq, "%s %d %s # SKIP %s\n",
			   kunit_status_to_ok_not_ok(success), 1, suite->name,
			   suite->status_comment);
	return 0;
}

static int debugfs_release(struct inode *inode, struct file *file)
{
	return single_release(inode, file);
}

static int debugfs_results_open(struct inode *inode, struct file *file)
{
	struct kunit_suite *suite;

	suite = (struct kunit_suite *)inode->i_private;

	return single_open(file, debugfs_print_results, suite);
}

/*
 * Print a usage message to the debugfs "run" file
 * (/sys/kernel/debug/kunit/<testsuite>/run) if opened.
 */
static int debugfs_print_run(struct seq_file *seq, void *v)
{
	struct kunit_suite *suite = (struct kunit_suite *)seq->private;

	seq_puts(seq, "Write to this file to trigger the test suite to run.\n");
	seq_printf(seq, "usage: echo \"any string\" > /sys/kernel/debugfs/kunit/%s/run\n",
			suite->name);
	return 0;
}

/*
 * The debugfs "run" file (/sys/kernel/debug/kunit/<testsuite>/run)
 * contains no information. Write to the file to trigger the test suite
 * to run.
 */
static int debugfs_run_open(struct inode *inode, struct file *file)
{
	struct kunit_suite *suite;

	suite = (struct kunit_suite *)inode->i_private;

	return single_open(file, debugfs_print_run, suite);
}

/*
 * Trigger a test suite to run by writing to the suite's "run" debugfs
 * file found at: /sys/kernel/debug/kunit/<testsuite>/run
 *
 * Note: what is written to this file will not be saved.
 */
static ssize_t debugfs_run(struct file *file,
		const char __user *buf, size_t count, loff_t *ppos)
{
	struct inode *f_inode = file->f_inode;
	struct kunit_suite *suite = (struct kunit_suite *) f_inode->i_private;

	__kunit_test_suites_init(&suite, 1, true);

	return count;
}

static const struct file_operations debugfs_results_fops = {
	.open = debugfs_results_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = debugfs_release,
};

static const struct file_operations debugfs_run_fops = {
	.open = debugfs_run_open,
	.read = seq_read,
	.write = debugfs_run,
	.llseek = seq_lseek,
	.release = debugfs_release,
};

void kunit_debugfs_create_suite(struct kunit_suite *suite)
{
	struct kunit_case *test_case;
	struct string_stream *stream;

	/* If suite log already allocated, do not create new debugfs files. */
	if (suite->log)
		return;

	/*
	 * Allocate logs before creating debugfs representation.
	 * The suite->log and test_case->log pointer are expected to be NULL
	 * if there isn't a log, so only set it if the log stream was created
	 * successfully.
	 */
	stream = alloc_string_stream(GFP_KERNEL);
	if (IS_ERR(stream))
		return;

	string_stream_set_append_newlines(stream, true);
	suite->log = stream;

	kunit_suite_for_each_test_case(suite, test_case) {
		stream = alloc_string_stream(GFP_KERNEL);
		if (IS_ERR(stream))
			goto err;

		string_stream_set_append_newlines(stream, true);
		test_case->log = stream;
	}

	suite->debugfs = debugfs_create_dir(suite->name, debugfs_rootdir);

	debugfs_create_file(KUNIT_DEBUGFS_RESULTS, S_IFREG | 0444,
			    suite->debugfs,
			    suite, &debugfs_results_fops);

	/* Do not create file to re-run test if test runs on init */
	if (!suite->is_init) {
		debugfs_create_file(KUNIT_DEBUGFS_RUN, S_IFREG | 0644,
				    suite->debugfs,
				    suite, &debugfs_run_fops);
	}
	return;

err:
	string_stream_destroy(suite->log);
	suite->log = NULL;
	kunit_suite_for_each_test_case(suite, test_case) {
		string_stream_destroy(test_case->log);
		test_case->log = NULL;
	}
}

void kunit_debugfs_destroy_suite(struct kunit_suite *suite)
{
	struct kunit_case *test_case;

	debugfs_remove_recursive(suite->debugfs);
	string_stream_destroy(suite->log);
	kunit_suite_for_each_test_case(suite, test_case)
		string_stream_destroy(test_case->log);
}
