xref: /linux/mm/damon/tests/core-kunit.h (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Data Access Monitor Unit Tests
4  *
5  * Copyright 2019 Amazon.com, Inc. or its affiliates.  All rights reserved.
6  *
7  * Author: SeongJae Park <sj@kernel.org>
8  */
9 
10 #ifdef CONFIG_DAMON_KUNIT_TEST
11 
12 #ifndef _DAMON_CORE_TEST_H
13 #define _DAMON_CORE_TEST_H
14 
15 #include <kunit/test.h>
16 
17 static void damon_test_regions(struct kunit *test)
18 {
19 	struct damon_region *r;
20 	struct damon_target *t;
21 
22 	r = damon_new_region(1, 2);
23 	if (!r)
24 		kunit_skip(test, "region alloc fail");
25 	KUNIT_EXPECT_EQ(test, 1ul, r->ar.start);
26 	KUNIT_EXPECT_EQ(test, 2ul, r->ar.end);
27 	KUNIT_EXPECT_EQ(test, 0u, r->nr_accesses);
28 
29 	t = damon_new_target();
30 	if (!t) {
31 		damon_free_region(r);
32 		kunit_skip(test, "target alloc fail");
33 	}
34 	KUNIT_EXPECT_EQ(test, 0u, damon_nr_regions(t));
35 
36 	damon_add_region(r, t);
37 	KUNIT_EXPECT_EQ(test, 1u, damon_nr_regions(t));
38 
39 	damon_destroy_region(r, t);
40 	KUNIT_EXPECT_EQ(test, 0u, damon_nr_regions(t));
41 
42 	damon_free_target(t);
43 }
44 
45 static unsigned int nr_damon_targets(struct damon_ctx *ctx)
46 {
47 	struct damon_target *t;
48 	unsigned int nr_targets = 0;
49 
50 	damon_for_each_target(t, ctx)
51 		nr_targets++;
52 
53 	return nr_targets;
54 }
55 
56 static void damon_test_target(struct kunit *test)
57 {
58 	struct damon_ctx *c = damon_new_ctx();
59 	struct damon_target *t;
60 
61 	if (!c)
62 		kunit_skip(test, "ctx alloc fail");
63 
64 	t = damon_new_target();
65 	if (!t) {
66 		damon_destroy_ctx(c);
67 		kunit_skip(test, "target alloc fail");
68 	}
69 	KUNIT_EXPECT_EQ(test, 0u, nr_damon_targets(c));
70 
71 	damon_add_target(c, t);
72 	KUNIT_EXPECT_EQ(test, 1u, nr_damon_targets(c));
73 
74 	damon_destroy_target(t, c);
75 	KUNIT_EXPECT_EQ(test, 0u, nr_damon_targets(c));
76 
77 	damon_destroy_ctx(c);
78 }
79 
80 /*
81  * Test kdamond_reset_aggregated()
82  *
83  * DAMON checks access to each region and aggregates this information as the
84  * access frequency of each region.  In detail, it increases '->nr_accesses' of
85  * regions that an access has confirmed.  'kdamond_reset_aggregated()' flushes
86  * the aggregated information ('->nr_accesses' of each regions) to the result
87  * buffer.  As a result of the flushing, the '->nr_accesses' of regions are
88  * initialized to zero.
89  */
90 static void damon_test_aggregate(struct kunit *test)
91 {
92 	struct damon_ctx *ctx = damon_new_ctx();
93 	unsigned long saddr[][3] = {{10, 20, 30}, {5, 42, 49}, {13, 33, 55} };
94 	unsigned long eaddr[][3] = {{15, 27, 40}, {31, 45, 55}, {23, 44, 66} };
95 	unsigned long accesses[][3] = {{42, 95, 84}, {10, 20, 30}, {0, 1, 2} };
96 	struct damon_target *t;
97 	struct damon_region *r;
98 	int it, ir;
99 
100 	if (!ctx)
101 		kunit_skip(test, "ctx alloc fail");
102 
103 	for (it = 0; it < 3; it++) {
104 		t = damon_new_target();
105 		if (!t) {
106 			damon_destroy_ctx(ctx);
107 			kunit_skip(test, "target alloc fail");
108 		}
109 		damon_add_target(ctx, t);
110 	}
111 
112 	it = 0;
113 	damon_for_each_target(t, ctx) {
114 		for (ir = 0; ir < 3; ir++) {
115 			r = damon_new_region(saddr[it][ir], eaddr[it][ir]);
116 			if (!r) {
117 				damon_destroy_ctx(ctx);
118 				kunit_skip(test, "region alloc fail");
119 			}
120 			r->nr_accesses = accesses[it][ir];
121 			r->nr_accesses_bp = accesses[it][ir] * 10000;
122 			damon_add_region(r, t);
123 		}
124 		it++;
125 	}
126 	kdamond_reset_aggregated(ctx);
127 	it = 0;
128 	damon_for_each_target(t, ctx) {
129 		ir = 0;
130 		/* '->nr_accesses' should be zeroed */
131 		damon_for_each_region(r, t) {
132 			KUNIT_EXPECT_EQ(test, 0u, r->nr_accesses);
133 			ir++;
134 		}
135 		/* regions should be preserved */
136 		KUNIT_EXPECT_EQ(test, 3, ir);
137 		it++;
138 	}
139 	/* targets also should be preserved */
140 	KUNIT_EXPECT_EQ(test, 3, it);
141 
142 	damon_destroy_ctx(ctx);
143 }
144 
145 static void damon_test_split_at(struct kunit *test)
146 {
147 	struct damon_target *t;
148 	struct damon_region *r, *r_new;
149 
150 	t = damon_new_target();
151 	if (!t)
152 		kunit_skip(test, "target alloc fail");
153 	r = damon_new_region(0, 100);
154 	if (!r) {
155 		damon_free_target(t);
156 		kunit_skip(test, "region alloc fail");
157 	}
158 	r->nr_accesses_bp = 420000;
159 	r->nr_accesses = 42;
160 	r->last_nr_accesses = 15;
161 	r->age = 10;
162 	damon_add_region(r, t);
163 	damon_split_region_at(t, r, 25);
164 	KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
165 	KUNIT_EXPECT_EQ(test, r->ar.end, 25ul);
166 
167 	r_new = damon_next_region(r);
168 	KUNIT_EXPECT_EQ(test, r_new->ar.start, 25ul);
169 	KUNIT_EXPECT_EQ(test, r_new->ar.end, 100ul);
170 
171 	KUNIT_EXPECT_EQ(test, r->nr_accesses_bp, r_new->nr_accesses_bp);
172 	KUNIT_EXPECT_EQ(test, r->nr_accesses, r_new->nr_accesses);
173 	KUNIT_EXPECT_EQ(test, r->last_nr_accesses, r_new->last_nr_accesses);
174 	KUNIT_EXPECT_EQ(test, r->age, r_new->age);
175 
176 	damon_free_target(t);
177 }
178 
179 static void damon_test_merge_two(struct kunit *test)
180 {
181 	struct damon_target *t;
182 	struct damon_region *r, *r2, *r3;
183 	int i;
184 
185 	t = damon_new_target();
186 	if (!t)
187 		kunit_skip(test, "target alloc fail");
188 	r = damon_new_region(0, 100);
189 	if (!r) {
190 		damon_free_target(t);
191 		kunit_skip(test, "region alloc fail");
192 	}
193 	r->nr_accesses = 10;
194 	r->nr_accesses_bp = 100000;
195 	r->age = 9;
196 	damon_add_region(r, t);
197 	r2 = damon_new_region(100, 300);
198 	if (!r2) {
199 		damon_free_target(t);
200 		kunit_skip(test, "second region alloc fail");
201 	}
202 	r2->nr_accesses = 20;
203 	r2->nr_accesses_bp = 200000;
204 	r2->age = 21;
205 	damon_add_region(r2, t);
206 
207 	damon_merge_two_regions(t, r, r2);
208 	KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
209 	KUNIT_EXPECT_EQ(test, r->ar.end, 300ul);
210 	KUNIT_EXPECT_EQ(test, r->nr_accesses, 16u);
211 	KUNIT_EXPECT_EQ(test, r->nr_accesses_bp, 160000u);
212 	KUNIT_EXPECT_EQ(test, r->age, 17u);
213 
214 	i = 0;
215 	damon_for_each_region(r3, t) {
216 		KUNIT_EXPECT_PTR_EQ(test, r, r3);
217 		i++;
218 	}
219 	KUNIT_EXPECT_EQ(test, i, 1);
220 
221 	damon_free_target(t);
222 }
223 
224 static struct damon_region *__nth_region_of(struct damon_target *t, int idx)
225 {
226 	struct damon_region *r;
227 	unsigned int i = 0;
228 
229 	damon_for_each_region(r, t) {
230 		if (i++ == idx)
231 			return r;
232 	}
233 
234 	return NULL;
235 }
236 
237 static void damon_test_merge_regions_of(struct kunit *test)
238 {
239 	struct damon_target *t;
240 	struct damon_region *r;
241 	unsigned long sa[] = {0, 100, 114, 122, 130, 156, 170, 184, 230};
242 	unsigned long ea[] = {100, 112, 122, 130, 156, 170, 184, 230, 10170};
243 	unsigned int nrs[] = {0, 0, 10, 10, 20, 30, 1, 2, 5};
244 
245 	unsigned long saddrs[] = {0, 114, 130, 156, 170, 230};
246 	unsigned long eaddrs[] = {112, 130, 156, 170, 230, 10170};
247 	int i;
248 
249 	t = damon_new_target();
250 	if (!t)
251 		kunit_skip(test, "target alloc fail");
252 	for (i = 0; i < ARRAY_SIZE(sa); i++) {
253 		r = damon_new_region(sa[i], ea[i]);
254 		if (!r) {
255 			damon_free_target(t);
256 			kunit_skip(test, "region alloc fail");
257 		}
258 		r->nr_accesses = nrs[i];
259 		r->nr_accesses_bp = nrs[i] * 10000;
260 		damon_add_region(r, t);
261 	}
262 
263 	damon_merge_regions_of(t, 9, 9999);
264 	/* 0-112, 114-130, 130-156, 156-170, 170-230, 230-10170 */
265 	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 6u);
266 	for (i = 0; i < 6; i++) {
267 		r = __nth_region_of(t, i);
268 		KUNIT_EXPECT_EQ(test, r->ar.start, saddrs[i]);
269 		KUNIT_EXPECT_EQ(test, r->ar.end, eaddrs[i]);
270 	}
271 	damon_free_target(t);
272 }
273 
274 static void damon_test_split_regions_of(struct kunit *test)
275 {
276 	struct damon_ctx *c;
277 	struct damon_target *t;
278 	struct damon_region *r;
279 	unsigned long sa[] = {0, 300, 500};
280 	unsigned long ea[] = {220, 400, 700};
281 	int i;
282 
283 	c = damon_new_ctx();
284 	if (!c)
285 		kunit_skip(test, "ctx alloc fail");
286 
287 	t = damon_new_target();
288 	if (!t) {
289 		damon_destroy_ctx(c);
290 		kunit_skip(test, "target alloc fail");
291 	}
292 	r = damon_new_region(0, 22);
293 	if (!r) {
294 		damon_free_target(t);
295 		damon_destroy_ctx(c);
296 		kunit_skip(test, "region alloc fail");
297 	}
298 	damon_add_region(r, t);
299 	damon_split_regions_of(c, t, 2, 1);
300 	KUNIT_EXPECT_LE(test, damon_nr_regions(t), 2u);
301 	damon_free_target(t);
302 
303 	t = damon_new_target();
304 	if (!t) {
305 		damon_destroy_ctx(c);
306 		kunit_skip(test, "second target alloc fail");
307 	}
308 	r = damon_new_region(0, 220);
309 	if (!r) {
310 		damon_free_target(t);
311 		damon_destroy_ctx(c);
312 		kunit_skip(test, "second region alloc fail");
313 	}
314 	damon_add_region(r, t);
315 	damon_split_regions_of(c, t, 4, 1);
316 	KUNIT_EXPECT_LE(test, damon_nr_regions(t), 4u);
317 	damon_free_target(t);
318 
319 	t = damon_new_target();
320 	if (!t) {
321 		damon_destroy_ctx(c);
322 		kunit_skip(test, "third target alloc fail");
323 	}
324 	for (i = 0; i < ARRAY_SIZE(sa); i++) {
325 		r = damon_new_region(sa[i], ea[i]);
326 		if (!r) {
327 			damon_free_target(t);
328 			damon_destroy_ctx(c);
329 			kunit_skip(test, "region alloc fail");
330 		}
331 		damon_add_region(r, t);
332 	}
333 	damon_split_regions_of(c, t, 4, 5);
334 	KUNIT_EXPECT_LE(test, damon_nr_regions(t), 12u);
335 	damon_for_each_region(r, t)
336 		KUNIT_EXPECT_GE(test, damon_sz_region(r) % 5ul, 0ul);
337 	damon_free_target(t);
338 
339 	damon_destroy_ctx(c);
340 }
341 
342 static void damon_test_ops_registration(struct kunit *test)
343 {
344 	struct damon_ctx *c = damon_new_ctx();
345 	struct damon_operations ops = {.id = DAMON_OPS_VADDR}, bak;
346 	bool need_cleanup = false;
347 
348 	if (!c)
349 		kunit_skip(test, "ctx alloc fail");
350 
351 	/* DAMON_OPS_VADDR is registered only if CONFIG_DAMON_VADDR is set */
352 	if (!damon_is_registered_ops(DAMON_OPS_VADDR)) {
353 		bak.id = DAMON_OPS_VADDR;
354 		KUNIT_EXPECT_EQ(test, damon_register_ops(&bak), 0);
355 		need_cleanup = true;
356 	}
357 
358 	/* DAMON_OPS_VADDR is ensured to be registered */
359 	KUNIT_EXPECT_EQ(test, damon_select_ops(c, DAMON_OPS_VADDR), 0);
360 
361 	/* Double-registration is prohibited */
362 	KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL);
363 
364 	/* Unknown ops id cannot be registered */
365 	KUNIT_EXPECT_EQ(test, damon_select_ops(c, NR_DAMON_OPS), -EINVAL);
366 
367 	/* Registration should success after unregistration */
368 	mutex_lock(&damon_ops_lock);
369 	bak = damon_registered_ops[DAMON_OPS_VADDR];
370 	damon_registered_ops[DAMON_OPS_VADDR] = (struct damon_operations){};
371 	mutex_unlock(&damon_ops_lock);
372 
373 	ops.id = DAMON_OPS_VADDR;
374 	KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), 0);
375 
376 	mutex_lock(&damon_ops_lock);
377 	damon_registered_ops[DAMON_OPS_VADDR] = bak;
378 	mutex_unlock(&damon_ops_lock);
379 
380 	/* Check double-registration failure again */
381 	KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL);
382 
383 	damon_destroy_ctx(c);
384 
385 	if (need_cleanup) {
386 		mutex_lock(&damon_ops_lock);
387 		damon_registered_ops[DAMON_OPS_VADDR] =
388 			(struct damon_operations){};
389 		mutex_unlock(&damon_ops_lock);
390 	}
391 }
392 
393 static void damon_test_set_regions_for(struct kunit *test,
394 		struct damon_addr_range *old_ranges, int sz_old_ranges,
395 		struct damon_addr_range *new_ranges, int sz_new_ranges,
396 		unsigned long min_region_sz,
397 		struct damon_addr_range *expect_ranges, int sz_expect_ranges)
398 {
399 	struct damon_target *t;
400 	struct damon_region *r;
401 	int i;
402 
403 	t = damon_new_target();
404 	if (!t)
405 		kunit_skip(test, "target alloc fail");
406 	for (i = 0; i < sz_old_ranges; i++) {
407 		r = damon_new_region(old_ranges[i].start, old_ranges[i].end);
408 		if (!r) {
409 			damon_destroy_target(t, NULL);
410 			kunit_skip(test, "%d-th r alloc fail\n", i);
411 		}
412 		damon_add_region(r, t);
413 	}
414 
415 	damon_set_regions(t, new_ranges, sz_new_ranges, min_region_sz);
416 
417 	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), sz_expect_ranges);
418 	if (damon_nr_regions(t) != sz_expect_ranges) {
419 		damon_destroy_target(t, NULL);
420 		return;
421 	}
422 	i = 0;
423 	damon_for_each_region(r, t) {
424 		KUNIT_EXPECT_EQ(test, r->ar.start, expect_ranges[i].start);
425 		KUNIT_EXPECT_EQ(test, r->ar.end, expect_ranges[i++].end);
426 	}
427 
428 	damon_destroy_target(t, NULL);
429 }
430 
431 static void damon_test_set_regions(struct kunit *test)
432 {
433 	/* Initial build up on empty target. */
434 	damon_test_set_regions_for(test,
435 			(struct damon_addr_range[]){}, 0,
436 			(struct damon_addr_range[]){
437 			{.start = 5, .end = 15},
438 			{.start = 15, .end = 25},
439 			}, 2,
440 			1,
441 			(struct damon_addr_range[]){
442 			{.start = 5, .end = 15},
443 			{.start = 15, .end = 25},
444 			}, 2);
445 	/* Un-intersecting regions should be removed. */
446 	damon_test_set_regions_for(test,
447 			(struct damon_addr_range[]){
448 			{.start = 4, .end = 16},
449 			{.start = 24, .end = 32},
450 			}, 2,
451 			(struct damon_addr_range[]){
452 			{.start = 18, .end = 23},
453 			}, 1,
454 			1,
455 			(struct damon_addr_range[]){
456 			{.start = 18, .end = 23},
457 			}, 1);
458 	/*
459 	 * Holes should be filled up with new regions.
460 	 *
461 	 * old:       [4,   16)        [24,     32)
462 	 * new:         [8,                 28)
463 	 * expect:      [8, 16)[16,24),[24, 28)
464 	 */
465 	damon_test_set_regions_for(test,
466 			(struct damon_addr_range[]){
467 			{.start = 4, .end = 16},
468 			{.start = 24, .end = 32},
469 			}, 2,
470 			(struct damon_addr_range[]){
471 			{.start = 8, .end = 28},
472 			}, 1,
473 			1,
474 			(struct damon_addr_range[]){
475 			{.start = 8, .end = 16},
476 			{.start = 16, .end = 24},
477 			{.start = 24, .end = 28},
478 			}, 3);
479 	/*
480 	 * New regions should be able to be appended.
481 	 *
482 	 * old:       [0, 4)[4,    17)
483 	 * new:       [0,       15)     [25, 40)
484 	 * expect:    [0, 4)[4, 15)     [25, 40)
485 	 */
486 	damon_test_set_regions_for(test,
487 			(struct damon_addr_range[]){
488 			{.start = 0, .end = 4},
489 			{.start = 4, .end = 17},
490 			}, 2,
491 			(struct damon_addr_range[]){
492 			{.start = 0, .end = 15},
493 			{.start = 25, .end = 40},
494 			}, 2,
495 			1,
496 			(struct damon_addr_range[]){
497 			{.start = 0, .end = 4},
498 			{.start = 4, .end = 15},
499 			{.start = 25, .end = 40},
500 			}, 3);
501 	/*
502 	 * New regions should be able to be inserted.
503 	 *
504 	 * old:       [0, 4)                      [42,    52)
505 	 * new:       [0,       15)     [25, 40)    [44, 50)
506 	 * expect:    [0,       15)     [25, 40)    [44, 50)
507 	 */
508 	damon_test_set_regions_for(test,
509 			(struct damon_addr_range[]){
510 			{.start = 0, .end = 4},
511 			{.start = 42, .end = 52},
512 			}, 2,
513 			(struct damon_addr_range[]){
514 			{.start = 0, .end = 15},
515 			{.start = 25, .end = 40},
516 			{.start = 44, .end = 50},
517 			}, 3,
518 			1,
519 			(struct damon_addr_range[]){
520 			{.start = 0, .end = 15},
521 			{.start = 25, .end = 40},
522 			{.start = 44, .end = 50},
523 			}, 3);
524 }
525 
526 static void damon_test_nr_accesses_to_accesses_bp(struct kunit *test)
527 {
528 	struct damon_attrs attrs = {
529 		.sample_interval = 10,
530 		.aggr_interval = ((unsigned long)UINT_MAX + 1) * 10
531 	};
532 
533 	/*
534 	 * In some cases such as 32bit architectures where UINT_MAX is
535 	 * ULONG_MAX, attrs.aggr_interval becomes zero.  Calling
536 	 * damon_nr_accesses_to_accesses_bp() in the case will cause
537 	 * divide-by-zero.  Such case is prohibited in normal execution since
538 	 * the caution is documented on the comment for the function, and
539 	 * damon_update_monitoring_results() does the check.  Skip the test in
540 	 * the case.
541 	 */
542 	if (!attrs.aggr_interval)
543 		kunit_skip(test, "aggr_interval is zero.");
544 
545 	KUNIT_EXPECT_EQ(test, damon_nr_accesses_to_accesses_bp(123, &attrs), 0);
546 }
547 
548 static void damon_test_update_monitoring_result(struct kunit *test)
549 {
550 	struct damon_attrs old_attrs = {
551 		.sample_interval = 10, .aggr_interval = 1000,};
552 	struct damon_attrs new_attrs;
553 	struct damon_region *r = damon_new_region(3, 7);
554 
555 	if (!r)
556 		kunit_skip(test, "region alloc fail");
557 
558 	r->nr_accesses = 15;
559 	r->nr_accesses_bp = 150000;
560 	r->age = 20;
561 
562 	new_attrs = (struct damon_attrs){
563 		.sample_interval = 100, .aggr_interval = 10000,};
564 	damon_update_monitoring_result(r, &old_attrs, &new_attrs, false);
565 	KUNIT_EXPECT_EQ(test, r->nr_accesses, 15);
566 	KUNIT_EXPECT_EQ(test, r->age, 2);
567 
568 	new_attrs = (struct damon_attrs){
569 		.sample_interval = 1, .aggr_interval = 1000};
570 	damon_update_monitoring_result(r, &old_attrs, &new_attrs, false);
571 	KUNIT_EXPECT_EQ(test, r->nr_accesses, 150);
572 	KUNIT_EXPECT_EQ(test, r->age, 2);
573 
574 	new_attrs = (struct damon_attrs){
575 		.sample_interval = 1, .aggr_interval = 100};
576 	damon_update_monitoring_result(r, &old_attrs, &new_attrs, false);
577 	KUNIT_EXPECT_EQ(test, r->nr_accesses, 150);
578 	KUNIT_EXPECT_EQ(test, r->age, 20);
579 
580 	damon_free_region(r);
581 }
582 
583 static void damon_test_set_attrs(struct kunit *test)
584 {
585 	struct damon_ctx *c = damon_new_ctx();
586 	struct damon_attrs valid_attrs = {
587 		.min_nr_regions = 10, .max_nr_regions = 1000,
588 		.sample_interval = 5000, .aggr_interval = 100000,};
589 	struct damon_attrs invalid_attrs;
590 
591 	if (!c)
592 		kunit_skip(test, "ctx alloc fail");
593 
594 	KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &valid_attrs), 0);
595 
596 	invalid_attrs = valid_attrs;
597 	invalid_attrs.min_nr_regions = 1;
598 	KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
599 
600 	invalid_attrs = valid_attrs;
601 	invalid_attrs.max_nr_regions = 9;
602 	KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
603 
604 	invalid_attrs = valid_attrs;
605 	invalid_attrs.aggr_interval = 4999;
606 	KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
607 
608 	damon_destroy_ctx(c);
609 }
610 
611 static void damon_test_moving_sum(struct kunit *test)
612 {
613 	unsigned int mvsum = 50000, nomvsum = 50000, len_window = 10;
614 	unsigned int new_values[] = {10000, 0, 10000, 0, 0, 0, 10000, 0, 0, 0};
615 	unsigned int expects[] = {55000, 50000, 55000, 50000, 45000, 40000,
616 		45000, 40000, 35000, 30000};
617 	int i;
618 
619 	for (i = 0; i < ARRAY_SIZE(new_values); i++) {
620 		mvsum = damon_moving_sum(mvsum, nomvsum, len_window,
621 				new_values[i]);
622 		KUNIT_EXPECT_EQ(test, mvsum, expects[i]);
623 	}
624 }
625 
626 static void damos_test_new_filter(struct kunit *test)
627 {
628 	struct damos_filter *filter;
629 
630 	filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true, false);
631 	if (!filter)
632 		kunit_skip(test, "filter alloc fail");
633 	KUNIT_EXPECT_EQ(test, filter->type, DAMOS_FILTER_TYPE_ANON);
634 	KUNIT_EXPECT_EQ(test, filter->matching, true);
635 	KUNIT_EXPECT_PTR_EQ(test, filter->list.prev, &filter->list);
636 	KUNIT_EXPECT_PTR_EQ(test, filter->list.next, &filter->list);
637 	damos_destroy_filter(filter);
638 }
639 
640 static void damos_test_commit_quota_goal_for(struct kunit *test,
641 		struct damos_quota_goal *dst,
642 		struct damos_quota_goal *src)
643 {
644 	u64 dst_last_psi_total = 0;
645 
646 	if (dst->metric == DAMOS_QUOTA_SOME_MEM_PSI_US)
647 		dst_last_psi_total = dst->last_psi_total;
648 	damos_commit_quota_goal(dst, src);
649 
650 	KUNIT_EXPECT_EQ(test, dst->metric, src->metric);
651 	KUNIT_EXPECT_EQ(test, dst->target_value, src->target_value);
652 	if (src->metric == DAMOS_QUOTA_USER_INPUT)
653 		KUNIT_EXPECT_EQ(test, dst->current_value, src->current_value);
654 	if (dst_last_psi_total && src->metric == DAMOS_QUOTA_SOME_MEM_PSI_US)
655 		KUNIT_EXPECT_EQ(test, dst->last_psi_total, dst_last_psi_total);
656 	switch (dst->metric) {
657 	case DAMOS_QUOTA_NODE_MEM_USED_BP:
658 	case DAMOS_QUOTA_NODE_MEM_FREE_BP:
659 		KUNIT_EXPECT_EQ(test, dst->nid, src->nid);
660 		break;
661 	case DAMOS_QUOTA_NODE_MEMCG_USED_BP:
662 	case DAMOS_QUOTA_NODE_MEMCG_FREE_BP:
663 		KUNIT_EXPECT_EQ(test, dst->nid, src->nid);
664 		KUNIT_EXPECT_EQ(test, dst->memcg_id, src->memcg_id);
665 		break;
666 	default:
667 		break;
668 	}
669 }
670 
671 static void damos_test_commit_quota_goal(struct kunit *test)
672 {
673 	struct damos_quota_goal dst = {
674 		.metric = DAMOS_QUOTA_SOME_MEM_PSI_US,
675 		.target_value = 1000,
676 		.current_value = 123,
677 		.last_psi_total = 456,
678 	};
679 
680 	damos_test_commit_quota_goal_for(test, &dst,
681 			&(struct damos_quota_goal){
682 			.metric = DAMOS_QUOTA_USER_INPUT,
683 			.target_value = 789,
684 			.current_value = 12});
685 	damos_test_commit_quota_goal_for(test, &dst,
686 			&(struct damos_quota_goal){
687 			.metric = DAMOS_QUOTA_NODE_MEM_FREE_BP,
688 			.target_value = 345,
689 			.current_value = 678,
690 			.nid = 9,
691 			});
692 	damos_test_commit_quota_goal_for(test, &dst,
693 			&(struct damos_quota_goal){
694 			.metric = DAMOS_QUOTA_NODE_MEM_USED_BP,
695 			.target_value = 12,
696 			.current_value = 345,
697 			.nid = 6,
698 			});
699 	damos_test_commit_quota_goal_for(test, &dst,
700 			&(struct damos_quota_goal){
701 			.metric = DAMOS_QUOTA_NODE_MEMCG_USED_BP,
702 			.target_value = 456,
703 			.current_value = 567,
704 			.nid = 6,
705 			.memcg_id = 7,
706 			});
707 	damos_test_commit_quota_goal_for(test, &dst,
708 			&(struct damos_quota_goal){
709 			.metric = DAMOS_QUOTA_NODE_MEMCG_FREE_BP,
710 			.target_value = 890,
711 			.current_value = 901,
712 			.nid = 10,
713 			.memcg_id = 1,
714 			});
715 	damos_test_commit_quota_goal_for(test, &dst,
716 			&(struct damos_quota_goal) {
717 			.metric = DAMOS_QUOTA_SOME_MEM_PSI_US,
718 			.target_value = 234,
719 			.current_value = 345,
720 			.last_psi_total = 567,
721 			});
722 }
723 
724 static void damos_test_commit_quota_goals_for(struct kunit *test,
725 		struct damos_quota_goal *dst_goals, int nr_dst_goals,
726 		struct damos_quota_goal *src_goals, int nr_src_goals)
727 {
728 	struct damos_quota dst, src;
729 	struct damos_quota_goal *goal, *next;
730 	bool skip = true;
731 	int i;
732 
733 	INIT_LIST_HEAD(&dst.goals);
734 	INIT_LIST_HEAD(&src.goals);
735 
736 	for (i = 0; i < nr_dst_goals; i++) {
737 		/*
738 		 * When nr_src_goals is smaller than dst_goals,
739 		 * damos_commit_quota_goals() will kfree() the dst goals.
740 		 * Make it kfree()-able.
741 		 */
742 		goal = damos_new_quota_goal(dst_goals[i].metric,
743 				dst_goals[i].target_value);
744 		if (!goal)
745 			goto out;
746 		damos_add_quota_goal(&dst, goal);
747 	}
748 	skip = false;
749 	for (i = 0; i < nr_src_goals; i++)
750 		damos_add_quota_goal(&src, &src_goals[i]);
751 
752 	damos_commit_quota_goals(&dst, &src);
753 
754 	i = 0;
755 	damos_for_each_quota_goal(goal, (&dst)) {
756 		KUNIT_EXPECT_EQ(test, goal->metric, src_goals[i].metric);
757 		KUNIT_EXPECT_EQ(test, goal->target_value,
758 				src_goals[i++].target_value);
759 	}
760 	KUNIT_EXPECT_EQ(test, i, nr_src_goals);
761 
762 out:
763 	damos_for_each_quota_goal_safe(goal, next, (&dst))
764 		damos_destroy_quota_goal(goal);
765 	if (skip)
766 		kunit_skip(test, "goal alloc fail");
767 }
768 
769 static void damos_test_commit_quota_goals(struct kunit *test)
770 {
771 	damos_test_commit_quota_goals_for(test,
772 			(struct damos_quota_goal[]){}, 0,
773 			(struct damos_quota_goal[]){
774 				{
775 				.metric = DAMOS_QUOTA_USER_INPUT,
776 				.target_value = 123,
777 				},
778 			}, 1);
779 	damos_test_commit_quota_goals_for(test,
780 			(struct damos_quota_goal[]){
781 				{
782 				.metric = DAMOS_QUOTA_USER_INPUT,
783 				.target_value = 234,
784 				},
785 
786 			}, 1,
787 			(struct damos_quota_goal[]){
788 				{
789 				.metric = DAMOS_QUOTA_USER_INPUT,
790 				.target_value = 345,
791 				},
792 			}, 1);
793 	damos_test_commit_quota_goals_for(test,
794 			(struct damos_quota_goal[]){
795 				{
796 				.metric = DAMOS_QUOTA_USER_INPUT,
797 				.target_value = 456,
798 				},
799 
800 			}, 1,
801 			(struct damos_quota_goal[]){}, 0);
802 }
803 
804 static void damos_test_commit_quota(struct kunit *test)
805 {
806 	struct damos_quota dst = {
807 		.reset_interval = 1,
808 		.ms = 2,
809 		.sz = 3,
810 		.goal_tuner = DAMOS_QUOTA_GOAL_TUNER_CONSIST,
811 		.fail_charge_num = 2,
812 		.fail_charge_denom = 3,
813 		.weight_sz = 4,
814 		.weight_nr_accesses = 5,
815 		.weight_age = 6,
816 	};
817 	struct damos_quota src = {
818 		.reset_interval = 7,
819 		.ms = 8,
820 		.sz = 9,
821 		.goal_tuner = DAMOS_QUOTA_GOAL_TUNER_TEMPORAL,
822 		.fail_charge_num = 1,
823 		.fail_charge_denom = 1024,
824 		.weight_sz = 10,
825 		.weight_nr_accesses = 11,
826 		.weight_age = 12,
827 	};
828 
829 	INIT_LIST_HEAD(&dst.goals);
830 	INIT_LIST_HEAD(&src.goals);
831 
832 	damos_commit_quota(&dst, &src);
833 
834 	KUNIT_EXPECT_EQ(test, dst.reset_interval, src.reset_interval);
835 	KUNIT_EXPECT_EQ(test, dst.ms, src.ms);
836 	KUNIT_EXPECT_EQ(test, dst.sz, src.sz);
837 	KUNIT_EXPECT_EQ(test, dst.goal_tuner, src.goal_tuner);
838 	KUNIT_EXPECT_EQ(test, dst.fail_charge_num, src.fail_charge_num);
839 	KUNIT_EXPECT_EQ(test, dst.fail_charge_denom, src.fail_charge_denom);
840 	KUNIT_EXPECT_EQ(test, dst.weight_sz, src.weight_sz);
841 	KUNIT_EXPECT_EQ(test, dst.weight_nr_accesses, src.weight_nr_accesses);
842 	KUNIT_EXPECT_EQ(test, dst.weight_age, src.weight_age);
843 }
844 
845 static int damos_test_help_dests_setup(struct damos_migrate_dests *dests,
846 		unsigned int *node_id_arr, unsigned int *weight_arr,
847 		size_t nr_dests)
848 {
849 	size_t i;
850 
851 	dests->node_id_arr = kmalloc_objs(*dests->node_id_arr, nr_dests);
852 	if (!dests->node_id_arr)
853 		return -ENOMEM;
854 	dests->weight_arr = kmalloc_objs(*dests->weight_arr, nr_dests);
855 	if (!dests->weight_arr) {
856 		kfree(dests->node_id_arr);
857 		dests->node_id_arr = NULL;
858 		return -ENOMEM;
859 	}
860 
861 	for (i = 0; i < nr_dests; i++) {
862 		dests->node_id_arr[i] = node_id_arr[i];
863 		dests->weight_arr[i] = weight_arr[i];
864 	}
865 	dests->nr_dests = nr_dests;
866 	return 0;
867 }
868 
869 static void damos_test_help_dests_free(struct damos_migrate_dests *dests)
870 {
871 	kfree(dests->node_id_arr);
872 	kfree(dests->weight_arr);
873 }
874 
875 static void damos_test_commit_dests_for(struct kunit *test,
876 		unsigned int *dst_node_id_arr, unsigned int *dst_weight_arr,
877 		size_t dst_nr_dests,
878 		unsigned int *src_node_id_arr, unsigned int *src_weight_arr,
879 		size_t src_nr_dests)
880 {
881 	struct damos_migrate_dests dst = {}, src = {};
882 	int i, err;
883 	bool skip = true;
884 
885 	err = damos_test_help_dests_setup(&dst, dst_node_id_arr,
886 			dst_weight_arr, dst_nr_dests);
887 	if (err)
888 		kunit_skip(test, "dests setup fail");
889 	err = damos_test_help_dests_setup(&src, src_node_id_arr,
890 			src_weight_arr, src_nr_dests);
891 	if (err) {
892 		damos_test_help_dests_free(&dst);
893 		kunit_skip(test, "src setup fail");
894 	}
895 	err = damos_commit_dests(&dst, &src);
896 	if (err)
897 		goto out;
898 	skip = false;
899 
900 	KUNIT_EXPECT_EQ(test, dst.nr_dests, src_nr_dests);
901 	for (i = 0; i < dst.nr_dests; i++) {
902 		KUNIT_EXPECT_EQ(test, dst.node_id_arr[i], src_node_id_arr[i]);
903 		KUNIT_EXPECT_EQ(test, dst.weight_arr[i], src_weight_arr[i]);
904 	}
905 
906 out:
907 	damos_test_help_dests_free(&dst);
908 	damos_test_help_dests_free(&src);
909 	if (skip)
910 		kunit_skip(test, "skip");
911 }
912 
913 static void damos_test_commit_dests(struct kunit *test)
914 {
915 	damos_test_commit_dests_for(test,
916 			(unsigned int[]){1, 2, 3}, (unsigned int[]){2, 3, 4},
917 			3,
918 			(unsigned int[]){4, 5, 6}, (unsigned int[]){5, 6, 7},
919 			3);
920 	damos_test_commit_dests_for(test,
921 			(unsigned int[]){1, 2}, (unsigned int[]){2, 3},
922 			2,
923 			(unsigned int[]){4, 5, 6}, (unsigned int[]){5, 6, 7},
924 			3);
925 	damos_test_commit_dests_for(test,
926 			NULL, NULL, 0,
927 			(unsigned int[]){4, 5, 6}, (unsigned int[]){5, 6, 7},
928 			3);
929 	damos_test_commit_dests_for(test,
930 			(unsigned int[]){1, 2, 3}, (unsigned int[]){2, 3, 4},
931 			3,
932 			(unsigned int[]){4, 5}, (unsigned int[]){5, 6}, 2);
933 	damos_test_commit_dests_for(test,
934 			(unsigned int[]){1, 2, 3}, (unsigned int[]){2, 3, 4},
935 			3,
936 			NULL, NULL, 0);
937 }
938 
939 static void damos_test_commit_filter_for(struct kunit *test,
940 		struct damos_filter *dst, struct damos_filter *src)
941 {
942 	damos_commit_filter(dst, src);
943 	KUNIT_EXPECT_EQ(test, dst->type, src->type);
944 	KUNIT_EXPECT_EQ(test, dst->matching, src->matching);
945 	KUNIT_EXPECT_EQ(test, dst->allow, src->allow);
946 	switch (src->type) {
947 	case DAMOS_FILTER_TYPE_MEMCG:
948 		KUNIT_EXPECT_EQ(test, dst->memcg_id, src->memcg_id);
949 		break;
950 	case DAMOS_FILTER_TYPE_ADDR:
951 		KUNIT_EXPECT_EQ(test, dst->addr_range.start,
952 				src->addr_range.start);
953 		KUNIT_EXPECT_EQ(test, dst->addr_range.end,
954 				src->addr_range.end);
955 		break;
956 	case DAMOS_FILTER_TYPE_TARGET:
957 		KUNIT_EXPECT_EQ(test, dst->target_idx, src->target_idx);
958 		break;
959 	case DAMOS_FILTER_TYPE_HUGEPAGE_SIZE:
960 		KUNIT_EXPECT_EQ(test, dst->sz_range.min, src->sz_range.min);
961 		KUNIT_EXPECT_EQ(test, dst->sz_range.max, src->sz_range.max);
962 		break;
963 	default:
964 		break;
965 	}
966 }
967 
968 static void damos_test_commit_filter(struct kunit *test)
969 {
970 	struct damos_filter dst = {
971 		.type = DAMOS_FILTER_TYPE_ACTIVE,
972 		.matching = false,
973 		.allow = false,
974 	};
975 
976 	damos_test_commit_filter_for(test, &dst,
977 			&(struct damos_filter){
978 			.type = DAMOS_FILTER_TYPE_ANON,
979 			.matching = true,
980 			.allow = true,
981 			});
982 	damos_test_commit_filter_for(test, &dst,
983 			&(struct damos_filter){
984 			.type = DAMOS_FILTER_TYPE_MEMCG,
985 			.matching = false,
986 			.allow = false,
987 			.memcg_id = 123,
988 			});
989 	damos_test_commit_filter_for(test, &dst,
990 			&(struct damos_filter){
991 			.type = DAMOS_FILTER_TYPE_YOUNG,
992 			.matching = true,
993 			.allow = true,
994 			});
995 	damos_test_commit_filter_for(test, &dst,
996 			&(struct damos_filter){
997 			.type = DAMOS_FILTER_TYPE_HUGEPAGE_SIZE,
998 			.matching = false,
999 			.allow = false,
1000 			.sz_range = {.min = 234, .max = 345},
1001 			});
1002 	damos_test_commit_filter_for(test, &dst,
1003 			&(struct damos_filter){
1004 			.type = DAMOS_FILTER_TYPE_UNMAPPED,
1005 			.matching = true,
1006 			.allow = true,
1007 			});
1008 	damos_test_commit_filter_for(test, &dst,
1009 			&(struct damos_filter){
1010 			.type = DAMOS_FILTER_TYPE_ADDR,
1011 			.matching = false,
1012 			.allow = false,
1013 			.addr_range = {.start = 456, .end = 567},
1014 			});
1015 	damos_test_commit_filter_for(test, &dst,
1016 			&(struct damos_filter){
1017 			.type = DAMOS_FILTER_TYPE_TARGET,
1018 			.matching = true,
1019 			.allow = true,
1020 			.target_idx = 6,
1021 			});
1022 }
1023 
1024 static void damos_test_help_initailize_scheme(struct damos *scheme)
1025 {
1026 	INIT_LIST_HEAD(&scheme->quota.goals);
1027 	INIT_LIST_HEAD(&scheme->core_filters);
1028 	INIT_LIST_HEAD(&scheme->ops_filters);
1029 }
1030 
1031 static void damos_test_commit_for(struct kunit *test, struct damos *dst,
1032 		struct damos *src)
1033 {
1034 	int err;
1035 
1036 	damos_test_help_initailize_scheme(dst);
1037 	damos_test_help_initailize_scheme(src);
1038 
1039 	err = damos_commit(dst, src);
1040 	if (err)
1041 		kunit_skip(test, "damos_commit fail");
1042 
1043 	KUNIT_EXPECT_EQ(test, dst->pattern.min_sz_region,
1044 			src->pattern.min_sz_region);
1045 	KUNIT_EXPECT_EQ(test, dst->pattern.max_sz_region,
1046 			src->pattern.max_sz_region);
1047 	KUNIT_EXPECT_EQ(test, dst->pattern.min_nr_accesses,
1048 			src->pattern.min_nr_accesses);
1049 	KUNIT_EXPECT_EQ(test, dst->pattern.max_nr_accesses,
1050 			src->pattern.max_nr_accesses);
1051 	KUNIT_EXPECT_EQ(test, dst->pattern.min_age_region,
1052 			src->pattern.min_age_region);
1053 	KUNIT_EXPECT_EQ(test, dst->pattern.max_age_region,
1054 			src->pattern.max_age_region);
1055 
1056 	KUNIT_EXPECT_EQ(test, dst->action, src->action);
1057 	KUNIT_EXPECT_EQ(test, dst->apply_interval_us, src->apply_interval_us);
1058 
1059 	KUNIT_EXPECT_EQ(test, dst->wmarks.metric, src->wmarks.metric);
1060 	KUNIT_EXPECT_EQ(test, dst->wmarks.interval, src->wmarks.interval);
1061 	KUNIT_EXPECT_EQ(test, dst->wmarks.high, src->wmarks.high);
1062 	KUNIT_EXPECT_EQ(test, dst->wmarks.mid, src->wmarks.mid);
1063 	KUNIT_EXPECT_EQ(test, dst->wmarks.low, src->wmarks.low);
1064 
1065 	switch (src->action) {
1066 	case DAMOS_MIGRATE_COLD:
1067 	case DAMOS_MIGRATE_HOT:
1068 		KUNIT_EXPECT_EQ(test, dst->target_nid, src->target_nid);
1069 		break;
1070 	default:
1071 		break;
1072 	}
1073 }
1074 
1075 static void damos_test_commit_pageout(struct kunit *test)
1076 {
1077 	damos_test_commit_for(test,
1078 			&(struct damos){
1079 				.pattern = (struct damos_access_pattern){
1080 					1, 2, 3, 4, 5, 6},
1081 				.action = DAMOS_PAGEOUT,
1082 				.apply_interval_us = 1000000,
1083 				.wmarks = (struct damos_watermarks){
1084 					DAMOS_WMARK_FREE_MEM_RATE,
1085 					900, 100, 50},
1086 			},
1087 			&(struct damos){
1088 				.pattern = (struct damos_access_pattern){
1089 					2, 3, 4, 5, 6, 7},
1090 				.action = DAMOS_PAGEOUT,
1091 				.apply_interval_us = 2000000,
1092 				.wmarks = (struct damos_watermarks){
1093 					DAMOS_WMARK_FREE_MEM_RATE,
1094 					800, 50, 30},
1095 			});
1096 }
1097 
1098 static void damos_test_commit_migrate_hot(struct kunit *test)
1099 {
1100 	damos_test_commit_for(test,
1101 			&(struct damos){
1102 				.pattern = (struct damos_access_pattern){
1103 					1, 2, 3, 4, 5, 6},
1104 				.action = DAMOS_PAGEOUT,
1105 				.apply_interval_us = 1000000,
1106 				.wmarks = (struct damos_watermarks){
1107 					DAMOS_WMARK_FREE_MEM_RATE,
1108 					900, 100, 50},
1109 			},
1110 			&(struct damos){
1111 				.pattern = (struct damos_access_pattern){
1112 					2, 3, 4, 5, 6, 7},
1113 				.action = DAMOS_MIGRATE_HOT,
1114 				.apply_interval_us = 2000000,
1115 				.target_nid = 5,
1116 			});
1117 }
1118 
1119 static struct damon_target *damon_test_help_setup_target(
1120 		unsigned long region_start_end[][2], int nr_regions)
1121 {
1122 	struct damon_target *t;
1123 	struct damon_region *r;
1124 	int i;
1125 
1126 	t = damon_new_target();
1127 	if (!t)
1128 		return NULL;
1129 	for (i = 0; i < nr_regions; i++) {
1130 		r = damon_new_region(region_start_end[i][0],
1131 				region_start_end[i][1]);
1132 		if (!r) {
1133 			damon_free_target(t);
1134 			return NULL;
1135 		}
1136 		damon_add_region(r, t);
1137 	}
1138 	return t;
1139 }
1140 
1141 static void damon_test_commit_target_regions_for(struct kunit *test,
1142 		unsigned long dst_start_end[][2], int nr_dst_regions,
1143 		unsigned long src_start_end[][2], int nr_src_regions,
1144 		unsigned long expect_start_end[][2], int nr_expect_regions)
1145 {
1146 	struct damon_target *dst_target, *src_target;
1147 	struct damon_region *r;
1148 	int i;
1149 
1150 	dst_target = damon_test_help_setup_target(dst_start_end, nr_dst_regions);
1151 	if (!dst_target)
1152 		kunit_skip(test, "dst target setup fail");
1153 	src_target = damon_test_help_setup_target(src_start_end, nr_src_regions);
1154 	if (!src_target) {
1155 		damon_free_target(dst_target);
1156 		kunit_skip(test, "src target setup fail");
1157 	}
1158 	damon_commit_target_regions(dst_target, src_target, 1);
1159 	i = 0;
1160 	damon_for_each_region(r, dst_target) {
1161 		KUNIT_EXPECT_EQ(test, r->ar.start, expect_start_end[i][0]);
1162 		KUNIT_EXPECT_EQ(test, r->ar.end, expect_start_end[i][1]);
1163 		i++;
1164 	}
1165 	KUNIT_EXPECT_EQ(test, damon_nr_regions(dst_target), nr_expect_regions);
1166 	KUNIT_EXPECT_EQ(test, i, nr_expect_regions);
1167 	damon_free_target(dst_target);
1168 	damon_free_target(src_target);
1169 }
1170 
1171 static void damon_test_commit_target_regions(struct kunit *test)
1172 {
1173 	damon_test_commit_target_regions_for(test,
1174 			(unsigned long[][2]) {{3, 8}, {8, 10}}, 2,
1175 			(unsigned long[][2]) {{4, 6}}, 1,
1176 			(unsigned long[][2]) {{4, 6}}, 1);
1177 	damon_test_commit_target_regions_for(test,
1178 			(unsigned long[][2]) {{3, 8}, {8, 10}}, 2,
1179 			(unsigned long[][2]) {}, 0,
1180 			(unsigned long[][2]) {{3, 8}, {8, 10}}, 2);
1181 }
1182 
1183 static void damon_test_commit_ctx(struct kunit *test)
1184 {
1185 	struct damon_ctx *src, *dst;
1186 
1187 	src = damon_new_ctx();
1188 	if (!src)
1189 		kunit_skip(test, "src alloc fail");
1190 	dst = damon_new_ctx();
1191 	if (!dst) {
1192 		damon_destroy_ctx(src);
1193 		kunit_skip(test, "dst alloc fail");
1194 	}
1195 	/* Only power of two min_region_sz is allowed. */
1196 	src->min_region_sz = 4096;
1197 	KUNIT_EXPECT_EQ(test, damon_commit_ctx(dst, src), 0);
1198 	src->min_region_sz = 4095;
1199 	KUNIT_EXPECT_EQ(test, damon_commit_ctx(dst, src), -EINVAL);
1200 	src->min_region_sz = 4096;
1201 	src->pause = true;
1202 	KUNIT_EXPECT_EQ(test, damon_commit_ctx(dst, src), 0);
1203 	KUNIT_EXPECT_TRUE(test, dst->pause);
1204 	damon_destroy_ctx(src);
1205 	damon_destroy_ctx(dst);
1206 }
1207 
1208 static void damos_test_filter_out(struct kunit *test)
1209 {
1210 	struct damon_target *t;
1211 	struct damon_region *r, *r2;
1212 	struct damos_filter *f;
1213 
1214 	f = damos_new_filter(DAMOS_FILTER_TYPE_ADDR, true, false);
1215 	if (!f)
1216 		kunit_skip(test, "filter alloc fail");
1217 	f->addr_range = (struct damon_addr_range){.start = 2, .end = 6};
1218 
1219 	t = damon_new_target();
1220 	if (!t) {
1221 		damos_destroy_filter(f);
1222 		kunit_skip(test, "target alloc fail");
1223 	}
1224 	r = damon_new_region(3, 5);
1225 	if (!r) {
1226 		damos_destroy_filter(f);
1227 		damon_free_target(t);
1228 		kunit_skip(test, "region alloc fail");
1229 	}
1230 	damon_add_region(r, t);
1231 
1232 	/* region in the range */
1233 	KUNIT_EXPECT_TRUE(test, damos_filter_match(NULL, t, r, f, 1));
1234 	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
1235 
1236 	/* region before the range */
1237 	r->ar.start = 1;
1238 	r->ar.end = 2;
1239 	KUNIT_EXPECT_FALSE(test,
1240 			damos_filter_match(NULL, t, r, f, 1));
1241 	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
1242 
1243 	/* region after the range */
1244 	r->ar.start = 6;
1245 	r->ar.end = 8;
1246 	KUNIT_EXPECT_FALSE(test,
1247 			damos_filter_match(NULL, t, r, f, 1));
1248 	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
1249 
1250 	/* region started before the range */
1251 	r->ar.start = 1;
1252 	r->ar.end = 4;
1253 	KUNIT_EXPECT_FALSE(test, damos_filter_match(NULL, t, r, f, 1));
1254 	/* filter should have split the region */
1255 	KUNIT_EXPECT_EQ(test, r->ar.start, 1);
1256 	KUNIT_EXPECT_EQ(test, r->ar.end, 2);
1257 	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
1258 	r2 = damon_next_region(r);
1259 	KUNIT_EXPECT_EQ(test, r2->ar.start, 2);
1260 	KUNIT_EXPECT_EQ(test, r2->ar.end, 4);
1261 	damon_destroy_region(r2, t);
1262 
1263 	/* region started in the range */
1264 	r->ar.start = 2;
1265 	r->ar.end = 8;
1266 	KUNIT_EXPECT_TRUE(test,
1267 			damos_filter_match(NULL, t, r, f, 1));
1268 	/* filter should have split the region */
1269 	KUNIT_EXPECT_EQ(test, r->ar.start, 2);
1270 	KUNIT_EXPECT_EQ(test, r->ar.end, 6);
1271 	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
1272 	r2 = damon_next_region(r);
1273 	KUNIT_EXPECT_EQ(test, r2->ar.start, 6);
1274 	KUNIT_EXPECT_EQ(test, r2->ar.end, 8);
1275 	damon_destroy_region(r2, t);
1276 
1277 	damon_free_target(t);
1278 	damos_free_filter(f);
1279 }
1280 
1281 static void damon_test_feed_loop_next_input(struct kunit *test)
1282 {
1283 	unsigned long last_input = 900000, current_score = 200;
1284 
1285 	/*
1286 	 * If current score is lower than the goal, which is always 10,000
1287 	 * (read the comment on damon_feed_loop_next_input()'s comment), next
1288 	 * input should be higher than the last input.
1289 	 */
1290 	KUNIT_EXPECT_GT(test,
1291 			damon_feed_loop_next_input(last_input, current_score),
1292 			last_input);
1293 
1294 	/*
1295 	 * If current score is higher than the goal, next input should be lower
1296 	 * than the last input.
1297 	 */
1298 	current_score = 250000000;
1299 	KUNIT_EXPECT_LT(test,
1300 			damon_feed_loop_next_input(last_input, current_score),
1301 			last_input);
1302 
1303 	/*
1304 	 * The next input depends on the distance between the current score and
1305 	 * the goal
1306 	 */
1307 	KUNIT_EXPECT_GT(test,
1308 			damon_feed_loop_next_input(last_input, 200),
1309 			damon_feed_loop_next_input(last_input, 2000));
1310 }
1311 
1312 static void damon_test_set_filters_default_reject(struct kunit *test)
1313 {
1314 	struct damos scheme;
1315 	struct damos_filter *target_filter, *anon_filter;
1316 
1317 	INIT_LIST_HEAD(&scheme.core_filters);
1318 	INIT_LIST_HEAD(&scheme.ops_filters);
1319 
1320 	damos_set_filters_default_reject(&scheme);
1321 	/*
1322 	 * No filter is installed.  Allow by default on both core and ops layer
1323 	 * filtering stages, since there are no filters at all.
1324 	 */
1325 	KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, false);
1326 	KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, false);
1327 
1328 	target_filter = damos_new_filter(DAMOS_FILTER_TYPE_TARGET, true, true);
1329 	if (!target_filter)
1330 		kunit_skip(test, "filter alloc fail");
1331 	damos_add_filter(&scheme, target_filter);
1332 	damos_set_filters_default_reject(&scheme);
1333 	/*
1334 	 * A core-handled allow-filter is installed.
1335 	 * Reject by default on core layer filtering stage due to the last
1336 	 * core-layer-filter's behavior.
1337 	 * Allow by default on ops layer filtering stage due to the absence of
1338 	 * ops layer filters.
1339 	 */
1340 	KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, true);
1341 	KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, false);
1342 
1343 	target_filter->allow = false;
1344 	damos_set_filters_default_reject(&scheme);
1345 	/*
1346 	 * A core-handled reject-filter is installed.
1347 	 * Allow by default on core layer filtering stage due to the last
1348 	 * core-layer-filter's behavior.
1349 	 * Allow by default on ops layer filtering stage due to the absence of
1350 	 * ops layer filters.
1351 	 */
1352 	KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, false);
1353 	KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, false);
1354 
1355 	anon_filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true, true);
1356 	if (!anon_filter) {
1357 		damos_free_filter(target_filter);
1358 		kunit_skip(test, "anon_filter alloc fail");
1359 	}
1360 	damos_add_filter(&scheme, anon_filter);
1361 
1362 	damos_set_filters_default_reject(&scheme);
1363 	/*
1364 	 * A core-handled reject-filter and ops-handled allow-filter are installed.
1365 	 * Allow by default on core layer filtering stage due to the existence
1366 	 * of the ops-handled filter.
1367 	 * Reject by default on ops layer filtering stage due to the last
1368 	 * ops-layer-filter's behavior.
1369 	 */
1370 	KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, false);
1371 	KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, true);
1372 
1373 	target_filter->allow = true;
1374 	damos_set_filters_default_reject(&scheme);
1375 	/*
1376 	 * A core-handled allow-filter and ops-handled allow-filter are
1377 	 * installed.
1378 	 * Allow by default on core layer filtering stage due to the existence
1379 	 * of the ops-handled filter.
1380 	 * Reject by default on ops layer filtering stage due to the last
1381 	 * ops-layer-filter's behavior.
1382 	 */
1383 	KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, false);
1384 	KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, true);
1385 
1386 	damos_free_filter(anon_filter);
1387 	damos_free_filter(target_filter);
1388 }
1389 
1390 static void damon_test_apply_min_nr_regions_for(struct kunit *test,
1391 		unsigned long sz_regions, unsigned long min_region_sz,
1392 		unsigned long min_nr_regions,
1393 		unsigned long max_region_sz_expect,
1394 		unsigned long nr_regions_expect)
1395 {
1396 	struct damon_ctx *ctx;
1397 	struct damon_target *t;
1398 	struct damon_region *r;
1399 	unsigned long max_region_size;
1400 
1401 	ctx = damon_new_ctx();
1402 	if (!ctx)
1403 		kunit_skip(test, "ctx alloc fail\n");
1404 	t = damon_new_target();
1405 	if (!t) {
1406 		damon_destroy_ctx(ctx);
1407 		kunit_skip(test, "target alloc fail\n");
1408 	}
1409 	damon_add_target(ctx, t);
1410 	r = damon_new_region(0, sz_regions);
1411 	if (!r) {
1412 		damon_destroy_ctx(ctx);
1413 		kunit_skip(test, "region alloc fail\n");
1414 	}
1415 	damon_add_region(r, t);
1416 
1417 	ctx->min_region_sz = min_region_sz;
1418 	ctx->attrs.min_nr_regions = min_nr_regions;
1419 	max_region_size = damon_apply_min_nr_regions(ctx);
1420 
1421 	KUNIT_EXPECT_EQ(test, max_region_size, max_region_sz_expect);
1422 	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), nr_regions_expect);
1423 
1424 	damon_destroy_ctx(ctx);
1425 }
1426 
1427 static void damon_test_apply_min_nr_regions(struct kunit *test)
1428 {
1429 	/* common, expected setup */
1430 	damon_test_apply_min_nr_regions_for(test, 10, 1, 10, 1, 10);
1431 	/* no zero size limit */
1432 	damon_test_apply_min_nr_regions_for(test, 10, 1, 15, 1, 10);
1433 	/* max size should be aligned by min_region_sz */
1434 	damon_test_apply_min_nr_regions_for(test, 10, 2, 2, 6, 2);
1435 	/*
1436 	 * when min_nr_regions and min_region_sz conflicts, min_region_sz wins.
1437 	 */
1438 	damon_test_apply_min_nr_regions_for(test, 10, 2, 10, 2, 5);
1439 }
1440 
1441 static void damon_test_is_last_region(struct kunit *test)
1442 {
1443 	struct damon_region *r;
1444 	struct damon_target *t;
1445 	int i;
1446 
1447 	t = damon_new_target();
1448 	if (!t)
1449 		kunit_skip(test, "target alloc fail\n");
1450 
1451 	for (i = 0; i < 4; i++) {
1452 		r = damon_new_region(i * 2, (i + 1) * 2);
1453 		if (!r) {
1454 			damon_free_target(t);
1455 			kunit_skip(test, "region alloc %d fail\n", i);
1456 		}
1457 		damon_add_region(r, t);
1458 		KUNIT_EXPECT_TRUE(test, damon_is_last_region(r, t));
1459 	}
1460 	damon_free_target(t);
1461 }
1462 
1463 static struct kunit_case damon_test_cases[] = {
1464 	KUNIT_CASE(damon_test_target),
1465 	KUNIT_CASE(damon_test_regions),
1466 	KUNIT_CASE(damon_test_aggregate),
1467 	KUNIT_CASE(damon_test_split_at),
1468 	KUNIT_CASE(damon_test_merge_two),
1469 	KUNIT_CASE(damon_test_merge_regions_of),
1470 	KUNIT_CASE(damon_test_split_regions_of),
1471 	KUNIT_CASE(damon_test_ops_registration),
1472 	KUNIT_CASE(damon_test_set_regions),
1473 	KUNIT_CASE(damon_test_nr_accesses_to_accesses_bp),
1474 	KUNIT_CASE(damon_test_update_monitoring_result),
1475 	KUNIT_CASE(damon_test_set_attrs),
1476 	KUNIT_CASE(damon_test_moving_sum),
1477 	KUNIT_CASE(damos_test_new_filter),
1478 	KUNIT_CASE(damos_test_commit_quota_goal),
1479 	KUNIT_CASE(damos_test_commit_quota_goals),
1480 	KUNIT_CASE(damos_test_commit_quota),
1481 	KUNIT_CASE(damos_test_commit_dests),
1482 	KUNIT_CASE(damos_test_commit_filter),
1483 	KUNIT_CASE(damos_test_commit_pageout),
1484 	KUNIT_CASE(damos_test_commit_migrate_hot),
1485 	KUNIT_CASE(damon_test_commit_target_regions),
1486 	KUNIT_CASE(damon_test_commit_ctx),
1487 	KUNIT_CASE(damos_test_filter_out),
1488 	KUNIT_CASE(damon_test_feed_loop_next_input),
1489 	KUNIT_CASE(damon_test_set_filters_default_reject),
1490 	KUNIT_CASE(damon_test_apply_min_nr_regions),
1491 	KUNIT_CASE(damon_test_is_last_region),
1492 	{},
1493 };
1494 
1495 static struct kunit_suite damon_test_suite = {
1496 	.name = "damon",
1497 	.test_cases = damon_test_cases,
1498 };
1499 kunit_test_suite(damon_test_suite);
1500 
1501 #endif /* _DAMON_CORE_TEST_H */
1502 
1503 #endif	/* CONFIG_DAMON_KUNIT_TEST */
1504