damon_set_regions() is one of the main DAMON kernel API functions that
set up the monitoring target memory region boundaries.  Implement unit
tests for verifying its basic functionalities.

Signed-off-by: SeongJae Park <[email protected]>
---
 mm/damon/tests/core-kunit.h | 142 ++++++++++++++++++++++++++++++------
 1 file changed, 120 insertions(+), 22 deletions(-)

diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index 866f716e5760d..1cfb8c176b873 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -390,41 +390,139 @@ static void damon_test_ops_registration(struct kunit 
*test)
        }
 }
 
-static void damon_test_set_regions(struct kunit *test)
+static void damon_test_set_regions_for(struct kunit *test,
+               struct damon_addr_range *old_ranges, int sz_old_ranges,
+               struct damon_addr_range *new_ranges, int sz_new_ranges,
+               unsigned long min_region_sz,
+               struct damon_addr_range *expect_ranges, int sz_expect_ranges)
 {
-       struct damon_target *t = damon_new_target();
-       struct damon_region *r1, *r2;
-       struct damon_addr_range range = {.start = 8, .end = 28};
-       unsigned long expects[] = {8, 16, 16, 24, 24, 28};
-       int expect_idx = 0;
+       struct damon_target *t;
        struct damon_region *r;
+       int i;
 
+       t = damon_new_target();
        if (!t)
                kunit_skip(test, "target alloc fail");
-       r1 = damon_new_region(4, 16);
-       if (!r1) {
-               damon_free_target(t);
-               kunit_skip(test, "region alloc fail");
-       }
-       r2 = damon_new_region(24, 32);
-       if (!r2) {
-               damon_free_target(t);
-               damon_free_region(r1);
-               kunit_skip(test, "second region alloc fail");
+       for (i = 0; i < sz_old_ranges; i++) {
+               r = damon_new_region(old_ranges[i].start, old_ranges[i].end);
+               if (!r) {
+                       damon_destroy_target(t, NULL);
+                       kunit_skip(test, "%d-th r alloc fail\n", i);
+               }
+               damon_add_region(r, t);
        }
 
-       damon_add_region(r1, t);
-       damon_add_region(r2, t);
-       damon_set_regions(t, &range, 1, 1);
+       damon_set_regions(t, new_ranges, sz_new_ranges, min_region_sz);
 
-       KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 3);
+       KUNIT_EXPECT_EQ(test, damon_nr_regions(t), sz_expect_ranges);
+       if (damon_nr_regions(t) != sz_expect_ranges) {
+               damon_destroy_target(t, NULL);
+               return;
+       }
+       i = 0;
        damon_for_each_region(r, t) {
-               KUNIT_EXPECT_EQ(test, r->ar.start, expects[expect_idx++]);
-               KUNIT_EXPECT_EQ(test, r->ar.end, expects[expect_idx++]);
+               KUNIT_EXPECT_EQ(test, r->ar.start, expect_ranges[i].start);
+               KUNIT_EXPECT_EQ(test, r->ar.end, expect_ranges[i++].end);
        }
+
        damon_destroy_target(t, NULL);
 }
 
+static void damon_test_set_regions(struct kunit *test)
+{
+       /* Initial build up on empty target. */
+       damon_test_set_regions_for(test,
+                       (struct damon_addr_range[]){}, 0,
+                       (struct damon_addr_range[]){
+                       {.start = 5, .end = 15},
+                       {.start = 15, .end = 25},
+                       }, 2,
+                       1,
+                       (struct damon_addr_range[]){
+                       {.start = 5, .end = 15},
+                       {.start = 15, .end = 25},
+                       }, 2);
+       /* Un-intersecting regions should be removed. */
+       damon_test_set_regions_for(test,
+                       (struct damon_addr_range[]){
+                       {.start = 4, .end = 16},
+                       {.start = 24, .end = 32},
+                       }, 2,
+                       (struct damon_addr_range[]){
+                       {.start = 18, .end = 23},
+                       }, 1,
+                       1,
+                       (struct damon_addr_range[]){
+                       {.start = 18, .end = 23},
+                       }, 1);
+       /*
+        * Holes should be filled up with new regions.
+        *
+        * old:       [4,   16)        [24,     32)
+        * new:         [8,                 28)
+        * expect:      [8, 16)[16,24),[24, 28)
+        */
+       damon_test_set_regions_for(test,
+                       (struct damon_addr_range[]){
+                       {.start = 4, .end = 16},
+                       {.start = 24, .end = 32},
+                       }, 2,
+                       (struct damon_addr_range[]){
+                       {.start = 8, .end = 28},
+                       }, 1,
+                       1,
+                       (struct damon_addr_range[]){
+                       {.start = 8, .end = 16},
+                       {.start = 16, .end = 24},
+                       {.start = 24, .end = 28},
+                       }, 3);
+       /*
+        * New regions should be able to be appended.
+        *
+        * old:       [0, 4)[4,    17)
+        * new:       [0,       15)     [25, 40)
+        * expect:    [0, 4)[4, 15)     [25, 40)
+        */
+       damon_test_set_regions_for(test,
+                       (struct damon_addr_range[]){
+                       {.start = 0, .end = 4},
+                       {.start = 4, .end = 17},
+                       }, 2,
+                       (struct damon_addr_range[]){
+                       {.start = 0, .end = 15},
+                       {.start = 25, .end = 40},
+                       }, 2,
+                       1,
+                       (struct damon_addr_range[]){
+                       {.start = 0, .end = 4},
+                       {.start = 4, .end = 15},
+                       {.start = 25, .end = 40},
+                       }, 3);
+       /*
+        * New regions should be able to be inserted.
+        *
+        * old:       [0, 4)                      [42,    52)
+        * new:       [0,       15)     [25, 40)    [44, 50)
+        * expect:    [0,       15)     [25, 40)    [44, 50)
+        */
+       damon_test_set_regions_for(test,
+                       (struct damon_addr_range[]){
+                       {.start = 0, .end = 4},
+                       {.start = 42, .end = 52},
+                       }, 2,
+                       (struct damon_addr_range[]){
+                       {.start = 0, .end = 15},
+                       {.start = 25, .end = 40},
+                       {.start = 44, .end = 50},
+                       }, 3,
+                       1,
+                       (struct damon_addr_range[]){
+                       {.start = 0, .end = 15},
+                       {.start = 25, .end = 40},
+                       {.start = 44, .end = 50},
+                       }, 3);
+}
+
 static void damon_test_nr_accesses_to_accesses_bp(struct kunit *test)
 {
        struct damon_attrs attrs = {
-- 
2.47.3

Reply via email to