162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * DAMON Debugfs Interface Unit Tests
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author: SeongJae Park <sjpark@amazon.de>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifdef CONFIG_DAMON_DBGFS_KUNIT_TEST
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef _DAMON_DBGFS_TEST_H
1162306a36Sopenharmony_ci#define _DAMON_DBGFS_TEST_H
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <kunit/test.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistatic void damon_dbgfs_test_str_to_ints(struct kunit *test)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	char *question;
1862306a36Sopenharmony_ci	int *answers;
1962306a36Sopenharmony_ci	int expected[] = {12, 35, 46};
2062306a36Sopenharmony_ci	ssize_t nr_integers = 0, i;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	question = "123";
2362306a36Sopenharmony_ci	answers = str_to_ints(question, strlen(question), &nr_integers);
2462306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, (ssize_t)1, nr_integers);
2562306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 123, answers[0]);
2662306a36Sopenharmony_ci	kfree(answers);
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	question = "123abc";
2962306a36Sopenharmony_ci	answers = str_to_ints(question, strlen(question), &nr_integers);
3062306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, (ssize_t)1, nr_integers);
3162306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 123, answers[0]);
3262306a36Sopenharmony_ci	kfree(answers);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	question = "a123";
3562306a36Sopenharmony_ci	answers = str_to_ints(question, strlen(question), &nr_integers);
3662306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, (ssize_t)0, nr_integers);
3762306a36Sopenharmony_ci	kfree(answers);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	question = "12 35";
4062306a36Sopenharmony_ci	answers = str_to_ints(question, strlen(question), &nr_integers);
4162306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, (ssize_t)2, nr_integers);
4262306a36Sopenharmony_ci	for (i = 0; i < nr_integers; i++)
4362306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, expected[i], answers[i]);
4462306a36Sopenharmony_ci	kfree(answers);
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	question = "12 35 46";
4762306a36Sopenharmony_ci	answers = str_to_ints(question, strlen(question), &nr_integers);
4862306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, (ssize_t)3, nr_integers);
4962306a36Sopenharmony_ci	for (i = 0; i < nr_integers; i++)
5062306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, expected[i], answers[i]);
5162306a36Sopenharmony_ci	kfree(answers);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	question = "12 35 abc 46";
5462306a36Sopenharmony_ci	answers = str_to_ints(question, strlen(question), &nr_integers);
5562306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, (ssize_t)2, nr_integers);
5662306a36Sopenharmony_ci	for (i = 0; i < 2; i++)
5762306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, expected[i], answers[i]);
5862306a36Sopenharmony_ci	kfree(answers);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	question = "";
6162306a36Sopenharmony_ci	answers = str_to_ints(question, strlen(question), &nr_integers);
6262306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, (ssize_t)0, nr_integers);
6362306a36Sopenharmony_ci	kfree(answers);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	question = "\n";
6662306a36Sopenharmony_ci	answers = str_to_ints(question, strlen(question), &nr_integers);
6762306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, (ssize_t)0, nr_integers);
6862306a36Sopenharmony_ci	kfree(answers);
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic void damon_dbgfs_test_set_targets(struct kunit *test)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	struct damon_ctx *ctx = dbgfs_new_ctx();
7462306a36Sopenharmony_ci	char buf[64];
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	/* Make DAMON consider target has no pid */
7762306a36Sopenharmony_ci	damon_select_ops(ctx, DAMON_OPS_PADDR);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	dbgfs_set_targets(ctx, 0, NULL);
8062306a36Sopenharmony_ci	sprint_target_ids(ctx, buf, 64);
8162306a36Sopenharmony_ci	KUNIT_EXPECT_STREQ(test, (char *)buf, "\n");
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	dbgfs_set_targets(ctx, 1, NULL);
8462306a36Sopenharmony_ci	sprint_target_ids(ctx, buf, 64);
8562306a36Sopenharmony_ci	KUNIT_EXPECT_STREQ(test, (char *)buf, "42\n");
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	dbgfs_set_targets(ctx, 0, NULL);
8862306a36Sopenharmony_ci	sprint_target_ids(ctx, buf, 64);
8962306a36Sopenharmony_ci	KUNIT_EXPECT_STREQ(test, (char *)buf, "\n");
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	dbgfs_destroy_ctx(ctx);
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic void damon_dbgfs_test_set_init_regions(struct kunit *test)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	struct damon_ctx *ctx = damon_new_ctx();
9762306a36Sopenharmony_ci	/* Each line represents one region in ``<target idx> <start> <end>`` */
9862306a36Sopenharmony_ci	char * const valid_inputs[] = {"1 10 20\n 1   20 30\n1 35 45",
9962306a36Sopenharmony_ci		"1 10 20\n",
10062306a36Sopenharmony_ci		"1 10 20\n0 39 59\n0 70 134\n  1  20 25\n",
10162306a36Sopenharmony_ci		""};
10262306a36Sopenharmony_ci	/* Reading the file again will show sorted, clean output */
10362306a36Sopenharmony_ci	char * const valid_expects[] = {"1 10 20\n1 20 30\n1 35 45\n",
10462306a36Sopenharmony_ci		"1 10 20\n",
10562306a36Sopenharmony_ci		"0 39 59\n0 70 134\n1 10 20\n1 20 25\n",
10662306a36Sopenharmony_ci		""};
10762306a36Sopenharmony_ci	char * const invalid_inputs[] = {"3 10 20\n",	/* target not exists */
10862306a36Sopenharmony_ci		"1 10 20\n 1 14 26\n",		/* regions overlap */
10962306a36Sopenharmony_ci		"0 10 20\n1 30 40\n 0 5 8"};	/* not sorted by address */
11062306a36Sopenharmony_ci	char *input, *expect;
11162306a36Sopenharmony_ci	int i, rc;
11262306a36Sopenharmony_ci	char buf[256];
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	damon_select_ops(ctx, DAMON_OPS_PADDR);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	dbgfs_set_targets(ctx, 3, NULL);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	/* Put valid inputs and check the results */
11962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(valid_inputs); i++) {
12062306a36Sopenharmony_ci		input = valid_inputs[i];
12162306a36Sopenharmony_ci		expect = valid_expects[i];
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci		rc = set_init_regions(ctx, input, strnlen(input, 256));
12462306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, rc, 0);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci		memset(buf, 0, 256);
12762306a36Sopenharmony_ci		sprint_init_regions(ctx, buf, 256);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		KUNIT_EXPECT_STREQ(test, (char *)buf, expect);
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci	/* Put invalid inputs and check the return error code */
13262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(invalid_inputs); i++) {
13362306a36Sopenharmony_ci		input = invalid_inputs[i];
13462306a36Sopenharmony_ci		pr_info("input: %s\n", input);
13562306a36Sopenharmony_ci		rc = set_init_regions(ctx, input, strnlen(input, 256));
13662306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, rc, -EINVAL);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci		memset(buf, 0, 256);
13962306a36Sopenharmony_ci		sprint_init_regions(ctx, buf, 256);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci		KUNIT_EXPECT_STREQ(test, (char *)buf, "");
14262306a36Sopenharmony_ci	}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	dbgfs_set_targets(ctx, 0, NULL);
14562306a36Sopenharmony_ci	damon_destroy_ctx(ctx);
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic struct kunit_case damon_test_cases[] = {
14962306a36Sopenharmony_ci	KUNIT_CASE(damon_dbgfs_test_str_to_ints),
15062306a36Sopenharmony_ci	KUNIT_CASE(damon_dbgfs_test_set_targets),
15162306a36Sopenharmony_ci	KUNIT_CASE(damon_dbgfs_test_set_init_regions),
15262306a36Sopenharmony_ci	{},
15362306a36Sopenharmony_ci};
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic struct kunit_suite damon_test_suite = {
15662306a36Sopenharmony_ci	.name = "damon-dbgfs",
15762306a36Sopenharmony_ci	.test_cases = damon_test_cases,
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_cikunit_test_suite(damon_test_suite);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci#endif /* _DAMON_TEST_H */
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci#endif	/* CONFIG_DAMON_KUNIT_TEST */
164