162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Data Access Monitor Unit Tests
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2019 Amazon.com, Inc. or its affiliates.  All rights reserved.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: SeongJae Park <sjpark@amazon.de>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifdef CONFIG_DAMON_KUNIT_TEST
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#ifndef _DAMON_CORE_TEST_H
1362306a36Sopenharmony_ci#define _DAMON_CORE_TEST_H
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <kunit/test.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic void damon_test_regions(struct kunit *test)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	struct damon_region *r;
2062306a36Sopenharmony_ci	struct damon_target *t;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	r = damon_new_region(1, 2);
2362306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 1ul, r->ar.start);
2462306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 2ul, r->ar.end);
2562306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 0u, r->nr_accesses);
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	t = damon_new_target();
2862306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 0u, damon_nr_regions(t));
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	damon_add_region(r, t);
3162306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 1u, damon_nr_regions(t));
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	damon_del_region(r, t);
3462306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 0u, damon_nr_regions(t));
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	damon_free_target(t);
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic unsigned int nr_damon_targets(struct damon_ctx *ctx)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	struct damon_target *t;
4262306a36Sopenharmony_ci	unsigned int nr_targets = 0;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	damon_for_each_target(t, ctx)
4562306a36Sopenharmony_ci		nr_targets++;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	return nr_targets;
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic void damon_test_target(struct kunit *test)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	struct damon_ctx *c = damon_new_ctx();
5362306a36Sopenharmony_ci	struct damon_target *t;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	t = damon_new_target();
5662306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 0u, nr_damon_targets(c));
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	damon_add_target(c, t);
5962306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 1u, nr_damon_targets(c));
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	damon_destroy_target(t);
6262306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 0u, nr_damon_targets(c));
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	damon_destroy_ctx(c);
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/*
6862306a36Sopenharmony_ci * Test kdamond_reset_aggregated()
6962306a36Sopenharmony_ci *
7062306a36Sopenharmony_ci * DAMON checks access to each region and aggregates this information as the
7162306a36Sopenharmony_ci * access frequency of each region.  In detail, it increases '->nr_accesses' of
7262306a36Sopenharmony_ci * regions that an access has confirmed.  'kdamond_reset_aggregated()' flushes
7362306a36Sopenharmony_ci * the aggregated information ('->nr_accesses' of each regions) to the result
7462306a36Sopenharmony_ci * buffer.  As a result of the flushing, the '->nr_accesses' of regions are
7562306a36Sopenharmony_ci * initialized to zero.
7662306a36Sopenharmony_ci */
7762306a36Sopenharmony_cistatic void damon_test_aggregate(struct kunit *test)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	struct damon_ctx *ctx = damon_new_ctx();
8062306a36Sopenharmony_ci	unsigned long saddr[][3] = {{10, 20, 30}, {5, 42, 49}, {13, 33, 55} };
8162306a36Sopenharmony_ci	unsigned long eaddr[][3] = {{15, 27, 40}, {31, 45, 55}, {23, 44, 66} };
8262306a36Sopenharmony_ci	unsigned long accesses[][3] = {{42, 95, 84}, {10, 20, 30}, {0, 1, 2} };
8362306a36Sopenharmony_ci	struct damon_target *t;
8462306a36Sopenharmony_ci	struct damon_region *r;
8562306a36Sopenharmony_ci	int it, ir;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	for (it = 0; it < 3; it++) {
8862306a36Sopenharmony_ci		t = damon_new_target();
8962306a36Sopenharmony_ci		damon_add_target(ctx, t);
9062306a36Sopenharmony_ci	}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	it = 0;
9362306a36Sopenharmony_ci	damon_for_each_target(t, ctx) {
9462306a36Sopenharmony_ci		for (ir = 0; ir < 3; ir++) {
9562306a36Sopenharmony_ci			r = damon_new_region(saddr[it][ir], eaddr[it][ir]);
9662306a36Sopenharmony_ci			r->nr_accesses = accesses[it][ir];
9762306a36Sopenharmony_ci			damon_add_region(r, t);
9862306a36Sopenharmony_ci		}
9962306a36Sopenharmony_ci		it++;
10062306a36Sopenharmony_ci	}
10162306a36Sopenharmony_ci	kdamond_reset_aggregated(ctx);
10262306a36Sopenharmony_ci	it = 0;
10362306a36Sopenharmony_ci	damon_for_each_target(t, ctx) {
10462306a36Sopenharmony_ci		ir = 0;
10562306a36Sopenharmony_ci		/* '->nr_accesses' should be zeroed */
10662306a36Sopenharmony_ci		damon_for_each_region(r, t) {
10762306a36Sopenharmony_ci			KUNIT_EXPECT_EQ(test, 0u, r->nr_accesses);
10862306a36Sopenharmony_ci			ir++;
10962306a36Sopenharmony_ci		}
11062306a36Sopenharmony_ci		/* regions should be preserved */
11162306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, 3, ir);
11262306a36Sopenharmony_ci		it++;
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci	/* targets also should be preserved */
11562306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, 3, it);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	damon_destroy_ctx(ctx);
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic void damon_test_split_at(struct kunit *test)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct damon_ctx *c = damon_new_ctx();
12362306a36Sopenharmony_ci	struct damon_target *t;
12462306a36Sopenharmony_ci	struct damon_region *r;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	t = damon_new_target();
12762306a36Sopenharmony_ci	r = damon_new_region(0, 100);
12862306a36Sopenharmony_ci	damon_add_region(r, t);
12962306a36Sopenharmony_ci	damon_split_region_at(t, r, 25);
13062306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
13162306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.end, 25ul);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	r = damon_next_region(r);
13462306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.start, 25ul);
13562306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.end, 100ul);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	damon_free_target(t);
13862306a36Sopenharmony_ci	damon_destroy_ctx(c);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic void damon_test_merge_two(struct kunit *test)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	struct damon_target *t;
14462306a36Sopenharmony_ci	struct damon_region *r, *r2, *r3;
14562306a36Sopenharmony_ci	int i;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	t = damon_new_target();
14862306a36Sopenharmony_ci	r = damon_new_region(0, 100);
14962306a36Sopenharmony_ci	r->nr_accesses = 10;
15062306a36Sopenharmony_ci	damon_add_region(r, t);
15162306a36Sopenharmony_ci	r2 = damon_new_region(100, 300);
15262306a36Sopenharmony_ci	r2->nr_accesses = 20;
15362306a36Sopenharmony_ci	damon_add_region(r2, t);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	damon_merge_two_regions(t, r, r2);
15662306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
15762306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.end, 300ul);
15862306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->nr_accesses, 16u);
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	i = 0;
16162306a36Sopenharmony_ci	damon_for_each_region(r3, t) {
16262306a36Sopenharmony_ci		KUNIT_EXPECT_PTR_EQ(test, r, r3);
16362306a36Sopenharmony_ci		i++;
16462306a36Sopenharmony_ci	}
16562306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, i, 1);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	damon_free_target(t);
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic struct damon_region *__nth_region_of(struct damon_target *t, int idx)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	struct damon_region *r;
17362306a36Sopenharmony_ci	unsigned int i = 0;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	damon_for_each_region(r, t) {
17662306a36Sopenharmony_ci		if (i++ == idx)
17762306a36Sopenharmony_ci			return r;
17862306a36Sopenharmony_ci	}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	return NULL;
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistatic void damon_test_merge_regions_of(struct kunit *test)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	struct damon_target *t;
18662306a36Sopenharmony_ci	struct damon_region *r;
18762306a36Sopenharmony_ci	unsigned long sa[] = {0, 100, 114, 122, 130, 156, 170, 184};
18862306a36Sopenharmony_ci	unsigned long ea[] = {100, 112, 122, 130, 156, 170, 184, 230};
18962306a36Sopenharmony_ci	unsigned int nrs[] = {0, 0, 10, 10, 20, 30, 1, 2};
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	unsigned long saddrs[] = {0, 114, 130, 156, 170};
19262306a36Sopenharmony_ci	unsigned long eaddrs[] = {112, 130, 156, 170, 230};
19362306a36Sopenharmony_ci	int i;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	t = damon_new_target();
19662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(sa); i++) {
19762306a36Sopenharmony_ci		r = damon_new_region(sa[i], ea[i]);
19862306a36Sopenharmony_ci		r->nr_accesses = nrs[i];
19962306a36Sopenharmony_ci		damon_add_region(r, t);
20062306a36Sopenharmony_ci	}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	damon_merge_regions_of(t, 9, 9999);
20362306a36Sopenharmony_ci	/* 0-112, 114-130, 130-156, 156-170 */
20462306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 5u);
20562306a36Sopenharmony_ci	for (i = 0; i < 5; i++) {
20662306a36Sopenharmony_ci		r = __nth_region_of(t, i);
20762306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, r->ar.start, saddrs[i]);
20862306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, r->ar.end, eaddrs[i]);
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci	damon_free_target(t);
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic void damon_test_split_regions_of(struct kunit *test)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	struct damon_ctx *c = damon_new_ctx();
21662306a36Sopenharmony_ci	struct damon_target *t;
21762306a36Sopenharmony_ci	struct damon_region *r;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	t = damon_new_target();
22062306a36Sopenharmony_ci	r = damon_new_region(0, 22);
22162306a36Sopenharmony_ci	damon_add_region(r, t);
22262306a36Sopenharmony_ci	damon_split_regions_of(t, 2);
22362306a36Sopenharmony_ci	KUNIT_EXPECT_LE(test, damon_nr_regions(t), 2u);
22462306a36Sopenharmony_ci	damon_free_target(t);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	t = damon_new_target();
22762306a36Sopenharmony_ci	r = damon_new_region(0, 220);
22862306a36Sopenharmony_ci	damon_add_region(r, t);
22962306a36Sopenharmony_ci	damon_split_regions_of(t, 4);
23062306a36Sopenharmony_ci	KUNIT_EXPECT_LE(test, damon_nr_regions(t), 4u);
23162306a36Sopenharmony_ci	damon_free_target(t);
23262306a36Sopenharmony_ci	damon_destroy_ctx(c);
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic void damon_test_ops_registration(struct kunit *test)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	struct damon_ctx *c = damon_new_ctx();
23862306a36Sopenharmony_ci	struct damon_operations ops, bak;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	/* DAMON_OPS_{V,P}ADDR are registered on subsys_initcall */
24162306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_select_ops(c, DAMON_OPS_VADDR), 0);
24262306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_select_ops(c, DAMON_OPS_PADDR), 0);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	/* Double-registration is prohibited */
24562306a36Sopenharmony_ci	ops.id = DAMON_OPS_VADDR;
24662306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL);
24762306a36Sopenharmony_ci	ops.id = DAMON_OPS_PADDR;
24862306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	/* Unknown ops id cannot be registered */
25162306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_select_ops(c, NR_DAMON_OPS), -EINVAL);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	/* Registration should success after unregistration */
25462306a36Sopenharmony_ci	mutex_lock(&damon_ops_lock);
25562306a36Sopenharmony_ci	bak = damon_registered_ops[DAMON_OPS_VADDR];
25662306a36Sopenharmony_ci	damon_registered_ops[DAMON_OPS_VADDR] = (struct damon_operations){};
25762306a36Sopenharmony_ci	mutex_unlock(&damon_ops_lock);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	ops.id = DAMON_OPS_VADDR;
26062306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), 0);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	mutex_lock(&damon_ops_lock);
26362306a36Sopenharmony_ci	damon_registered_ops[DAMON_OPS_VADDR] = bak;
26462306a36Sopenharmony_ci	mutex_unlock(&damon_ops_lock);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	/* Check double-registration failure again */
26762306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL);
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic void damon_test_set_regions(struct kunit *test)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	struct damon_target *t = damon_new_target();
27362306a36Sopenharmony_ci	struct damon_region *r1 = damon_new_region(4, 16);
27462306a36Sopenharmony_ci	struct damon_region *r2 = damon_new_region(24, 32);
27562306a36Sopenharmony_ci	struct damon_addr_range range = {.start = 8, .end = 28};
27662306a36Sopenharmony_ci	unsigned long expects[] = {8, 16, 16, 24, 24, 28};
27762306a36Sopenharmony_ci	int expect_idx = 0;
27862306a36Sopenharmony_ci	struct damon_region *r;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	damon_add_region(r1, t);
28162306a36Sopenharmony_ci	damon_add_region(r2, t);
28262306a36Sopenharmony_ci	damon_set_regions(t, &range, 1);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 3);
28562306a36Sopenharmony_ci	damon_for_each_region(r, t) {
28662306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, r->ar.start, expects[expect_idx++]);
28762306a36Sopenharmony_ci		KUNIT_EXPECT_EQ(test, r->ar.end, expects[expect_idx++]);
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci	damon_destroy_target(t);
29062306a36Sopenharmony_ci}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cistatic void damon_test_update_monitoring_result(struct kunit *test)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	struct damon_attrs old_attrs = {
29562306a36Sopenharmony_ci		.sample_interval = 10, .aggr_interval = 1000,};
29662306a36Sopenharmony_ci	struct damon_attrs new_attrs;
29762306a36Sopenharmony_ci	struct damon_region *r = damon_new_region(3, 7);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	r->nr_accesses = 15;
30062306a36Sopenharmony_ci	r->age = 20;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	new_attrs = (struct damon_attrs){
30362306a36Sopenharmony_ci		.sample_interval = 100, .aggr_interval = 10000,};
30462306a36Sopenharmony_ci	damon_update_monitoring_result(r, &old_attrs, &new_attrs);
30562306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->nr_accesses, 15);
30662306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->age, 2);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	new_attrs = (struct damon_attrs){
30962306a36Sopenharmony_ci		.sample_interval = 1, .aggr_interval = 1000};
31062306a36Sopenharmony_ci	damon_update_monitoring_result(r, &old_attrs, &new_attrs);
31162306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->nr_accesses, 150);
31262306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->age, 2);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	new_attrs = (struct damon_attrs){
31562306a36Sopenharmony_ci		.sample_interval = 1, .aggr_interval = 100};
31662306a36Sopenharmony_ci	damon_update_monitoring_result(r, &old_attrs, &new_attrs);
31762306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->nr_accesses, 150);
31862306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->age, 20);
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic void damon_test_set_attrs(struct kunit *test)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	struct damon_ctx *c = damon_new_ctx();
32462306a36Sopenharmony_ci	struct damon_attrs valid_attrs = {
32562306a36Sopenharmony_ci		.min_nr_regions = 10, .max_nr_regions = 1000,
32662306a36Sopenharmony_ci		.sample_interval = 5000, .aggr_interval = 100000,};
32762306a36Sopenharmony_ci	struct damon_attrs invalid_attrs;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &valid_attrs), 0);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	invalid_attrs = valid_attrs;
33262306a36Sopenharmony_ci	invalid_attrs.min_nr_regions = 1;
33362306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	invalid_attrs = valid_attrs;
33662306a36Sopenharmony_ci	invalid_attrs.max_nr_regions = 9;
33762306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	invalid_attrs = valid_attrs;
34062306a36Sopenharmony_ci	invalid_attrs.aggr_interval = 4999;
34162306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
34262306a36Sopenharmony_ci}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_cistatic void damos_test_new_filter(struct kunit *test)
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	struct damos_filter *filter;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true);
34962306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, filter->type, DAMOS_FILTER_TYPE_ANON);
35062306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, filter->matching, true);
35162306a36Sopenharmony_ci	KUNIT_EXPECT_PTR_EQ(test, filter->list.prev, &filter->list);
35262306a36Sopenharmony_ci	KUNIT_EXPECT_PTR_EQ(test, filter->list.next, &filter->list);
35362306a36Sopenharmony_ci	damos_destroy_filter(filter);
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_cistatic void damos_test_filter_out(struct kunit *test)
35762306a36Sopenharmony_ci{
35862306a36Sopenharmony_ci	struct damon_target *t;
35962306a36Sopenharmony_ci	struct damon_region *r, *r2;
36062306a36Sopenharmony_ci	struct damos_filter *f;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	f = damos_new_filter(DAMOS_FILTER_TYPE_ADDR, true);
36362306a36Sopenharmony_ci	f->addr_range = (struct damon_addr_range){
36462306a36Sopenharmony_ci		.start = DAMON_MIN_REGION * 2, .end = DAMON_MIN_REGION * 6};
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	t = damon_new_target();
36762306a36Sopenharmony_ci	r = damon_new_region(DAMON_MIN_REGION * 3, DAMON_MIN_REGION * 5);
36862306a36Sopenharmony_ci	damon_add_region(r, t);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	/* region in the range */
37162306a36Sopenharmony_ci	KUNIT_EXPECT_TRUE(test, __damos_filter_out(NULL, t, r, f));
37262306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	/* region before the range */
37562306a36Sopenharmony_ci	r->ar.start = DAMON_MIN_REGION * 1;
37662306a36Sopenharmony_ci	r->ar.end = DAMON_MIN_REGION * 2;
37762306a36Sopenharmony_ci	KUNIT_EXPECT_FALSE(test, __damos_filter_out(NULL, t, r, f));
37862306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	/* region after the range */
38162306a36Sopenharmony_ci	r->ar.start = DAMON_MIN_REGION * 6;
38262306a36Sopenharmony_ci	r->ar.end = DAMON_MIN_REGION * 8;
38362306a36Sopenharmony_ci	KUNIT_EXPECT_FALSE(test, __damos_filter_out(NULL, t, r, f));
38462306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	/* region started before the range */
38762306a36Sopenharmony_ci	r->ar.start = DAMON_MIN_REGION * 1;
38862306a36Sopenharmony_ci	r->ar.end = DAMON_MIN_REGION * 4;
38962306a36Sopenharmony_ci	KUNIT_EXPECT_FALSE(test, __damos_filter_out(NULL, t, r, f));
39062306a36Sopenharmony_ci	/* filter should have split the region */
39162306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.start, DAMON_MIN_REGION * 1);
39262306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.end, DAMON_MIN_REGION * 2);
39362306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
39462306a36Sopenharmony_ci	r2 = damon_next_region(r);
39562306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r2->ar.start, DAMON_MIN_REGION * 2);
39662306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r2->ar.end, DAMON_MIN_REGION * 4);
39762306a36Sopenharmony_ci	damon_destroy_region(r2, t);
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	/* region started in the range */
40062306a36Sopenharmony_ci	r->ar.start = DAMON_MIN_REGION * 2;
40162306a36Sopenharmony_ci	r->ar.end = DAMON_MIN_REGION * 8;
40262306a36Sopenharmony_ci	KUNIT_EXPECT_TRUE(test, __damos_filter_out(NULL, t, r, f));
40362306a36Sopenharmony_ci	/* filter should have split the region */
40462306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.start, DAMON_MIN_REGION * 2);
40562306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r->ar.end, DAMON_MIN_REGION * 6);
40662306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
40762306a36Sopenharmony_ci	r2 = damon_next_region(r);
40862306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r2->ar.start, DAMON_MIN_REGION * 6);
40962306a36Sopenharmony_ci	KUNIT_EXPECT_EQ(test, r2->ar.end, DAMON_MIN_REGION * 8);
41062306a36Sopenharmony_ci	damon_destroy_region(r2, t);
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	damon_free_target(t);
41362306a36Sopenharmony_ci	damos_free_filter(f);
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic struct kunit_case damon_test_cases[] = {
41762306a36Sopenharmony_ci	KUNIT_CASE(damon_test_target),
41862306a36Sopenharmony_ci	KUNIT_CASE(damon_test_regions),
41962306a36Sopenharmony_ci	KUNIT_CASE(damon_test_aggregate),
42062306a36Sopenharmony_ci	KUNIT_CASE(damon_test_split_at),
42162306a36Sopenharmony_ci	KUNIT_CASE(damon_test_merge_two),
42262306a36Sopenharmony_ci	KUNIT_CASE(damon_test_merge_regions_of),
42362306a36Sopenharmony_ci	KUNIT_CASE(damon_test_split_regions_of),
42462306a36Sopenharmony_ci	KUNIT_CASE(damon_test_ops_registration),
42562306a36Sopenharmony_ci	KUNIT_CASE(damon_test_set_regions),
42662306a36Sopenharmony_ci	KUNIT_CASE(damon_test_update_monitoring_result),
42762306a36Sopenharmony_ci	KUNIT_CASE(damon_test_set_attrs),
42862306a36Sopenharmony_ci	KUNIT_CASE(damos_test_new_filter),
42962306a36Sopenharmony_ci	KUNIT_CASE(damos_test_filter_out),
43062306a36Sopenharmony_ci	{},
43162306a36Sopenharmony_ci};
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_cistatic struct kunit_suite damon_test_suite = {
43462306a36Sopenharmony_ci	.name = "damon",
43562306a36Sopenharmony_ci	.test_cases = damon_test_cases,
43662306a36Sopenharmony_ci};
43762306a36Sopenharmony_cikunit_test_suite(damon_test_suite);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci#endif /* _DAMON_CORE_TEST_H */
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci#endif	/* CONFIG_DAMON_KUNIT_TEST */
442