[PATCH 5/5] binder: encapsulate individual alloc test cases

Tiffany Yang posted 5 patches 3 months, 1 week ago
There is a newer version of this series
[PATCH 5/5] binder: encapsulate individual alloc test cases
Posted by Tiffany Yang 3 months, 1 week ago
Each case tested by the binder allocator test is defined by 3 parameters:
the end alignment type of each requested buffer allocation, whether those
buffers share the front or back pages of the allotted address space, and
the order in which those buffers should be released. The alignment type
represents how a binder buffer may be laid out within or across page
boundaries and relative to other buffers, and it's used along with
whether the buffers cover part (sharing the front pages) of or all
(sharing the back pages) of the vma to calculate the sizes passed into
each test.

binder_alloc_test_alloc recursively generates each possible arrangement
of alignment types and then tests that the binder_alloc code tracks pages
correctly when those buffers are allocated and then freed in every
possible order at both ends of the address space. While they provide
comprehensive coverage, they are poor candidates to be represented as
KUnit test cases, which must be statically enumerated. For 5 buffers and
5 end alignment types, the test case array would have 750,000 entries.
This change structures the recursive calls into meaningful test cases so
that failures are easier to interpret.

Signed-off-by: Tiffany Yang <ynaffit@google.com>
---
 drivers/android/tests/binder_alloc_kunit.c | 234 ++++++++++++++++-----
 1 file changed, 181 insertions(+), 53 deletions(-)

diff --git a/drivers/android/tests/binder_alloc_kunit.c b/drivers/android/tests/binder_alloc_kunit.c
index 500b21246c99..745560cf0f18 100644
--- a/drivers/android/tests/binder_alloc_kunit.c
+++ b/drivers/android/tests/binder_alloc_kunit.c
@@ -24,7 +24,16 @@ MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
 #define BUFFER_NUM 5
 #define BUFFER_MIN_SIZE (PAGE_SIZE / 8)
 
-static int binder_alloc_test_failures;
+#define FREESEQ_BUFLEN ((3 * BUFFER_NUM) + 1)
+
+#define ALIGN_TYPE_STRLEN (12)
+
+#define ALIGNMENTS_BUFLEN (((ALIGN_TYPE_STRLEN + 6) * BUFFER_NUM) + 1)
+
+#define PRINT_ALL_CASES (0)
+
+/* 5^5 alignment combinations * 2 places to share pages * 5! free sequences */
+#define TOTAL_EXHAUSTIVE_CASES (3125 * 2 * 120)
 
 /**
  * enum buf_end_align_type - Page alignment of a buffer
@@ -86,18 +95,49 @@ enum buf_end_align_type {
 	LOOP_END,
 };
 
-static void pr_err_size_seq(struct kunit *test, size_t *sizes, int *seq)
+static const char *const buf_end_align_type_strs[LOOP_END] = {
+	[SAME_PAGE_UNALIGNED] = "SP_UNALIGNED",
+	[SAME_PAGE_ALIGNED]   = " SP_ALIGNED ",
+	[NEXT_PAGE_UNALIGNED] = "NP_UNALIGNED",
+	[NEXT_PAGE_ALIGNED]   = " NP_ALIGNED ",
+	[NEXT_NEXT_UNALIGNED] = "NN_UNALIGNED",
+};
+
+struct binder_alloc_test_case_info {
+	size_t *buffer_sizes;
+	int *free_sequence;
+	char alignments[ALIGNMENTS_BUFLEN];
+	bool front_pages;
+};
+
+static void stringify_free_seq(struct kunit *test, int *seq, char *buf,
+			       size_t buf_len)
 {
+	size_t bytes = 0;
 	int i;
 
-	kunit_err(test, "alloc sizes: ");
-	for (i = 0; i < BUFFER_NUM; i++)
-		pr_cont("[%zu]", sizes[i]);
-	pr_cont("\n");
-	kunit_err(test, "free seq: ");
-	for (i = 0; i < BUFFER_NUM; i++)
-		pr_cont("[%d]", seq[i]);
-	pr_cont("\n");
+	for (i = 0; i < BUFFER_NUM; i++) {
+		bytes += snprintf(buf + bytes, buf_len - bytes, "[%d]", seq[i]);
+		if (bytes >= buf_len)
+			break;
+	}
+	KUNIT_EXPECT_LT(test, bytes, buf_len);
+}
+
+static void stringify_alignments(struct kunit *test, int *alignments,
+				 char *buf, size_t buf_len)
+{
+	size_t bytes = 0;
+	int i;
+
+	for (i = 0; i < BUFFER_NUM; i++) {
+		bytes += snprintf(buf + bytes, buf_len - bytes, "[ %d:%s ]", i,
+				  buf_end_align_type_strs[alignments[i]]);
+		if (bytes >= buf_len)
+			break;
+	}
+
+	KUNIT_EXPECT_LT(test, bytes, buf_len);
 }
 
 static bool check_buffer_pages_allocated(struct kunit *test,
@@ -124,28 +164,30 @@ static bool check_buffer_pages_allocated(struct kunit *test,
 	return true;
 }
 
-static void binder_alloc_test_alloc_buf(struct kunit *test,
-					struct binder_alloc *alloc,
-					struct binder_buffer *buffers[],
-					size_t *sizes, int *seq)
+static unsigned long binder_alloc_test_alloc_buf(struct kunit *test,
+						 struct binder_alloc *alloc,
+						 struct binder_buffer *buffers[],
+						 size_t *sizes, int *seq)
 {
+	unsigned long failures = 0;
 	int i;
 
 	for (i = 0; i < BUFFER_NUM; i++) {
 		buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0);
 		if (IS_ERR(buffers[i]) ||
-		    !check_buffer_pages_allocated(test, alloc, buffers[i], sizes[i])) {
-			pr_err_size_seq(test, sizes, seq);
-			binder_alloc_test_failures++;
-		}
+		    !check_buffer_pages_allocated(test, alloc, buffers[i], sizes[i]))
+			failures++;
 	}
+
+	return failures;
 }
 
-static void binder_alloc_test_free_buf(struct kunit *test,
-				       struct binder_alloc *alloc,
-				       struct binder_buffer *buffers[],
-				       size_t *sizes, int *seq, size_t end)
+static unsigned long binder_alloc_test_free_buf(struct kunit *test,
+						struct binder_alloc *alloc,
+						struct binder_buffer *buffers[],
+						size_t *sizes, int *seq, size_t end)
 {
+	unsigned long failures = 0;
 	int i;
 
 	for (i = 0; i < BUFFER_NUM; i++)
@@ -153,17 +195,19 @@ static void binder_alloc_test_free_buf(struct kunit *test,
 
 	for (i = 0; i <= (end - 1) / PAGE_SIZE; i++) {
 		if (list_empty(page_to_lru(alloc->pages[i]))) {
-			pr_err_size_seq(test, sizes, seq);
 			kunit_err(test, "expect lru but is %s at page index %d\n",
 				  alloc->pages[i] ? "alloc" : "free", i);
-			binder_alloc_test_failures++;
+			failures++;
 		}
 	}
+
+	return failures;
 }
 
-static void binder_alloc_test_free_page(struct kunit *test,
-					struct binder_alloc *alloc)
+static unsigned long binder_alloc_test_free_page(struct kunit *test,
+						 struct binder_alloc *alloc)
 {
+	unsigned long failures = 0;
 	unsigned long count;
 	int i;
 
@@ -177,27 +221,70 @@ static void binder_alloc_test_free_page(struct kunit *test,
 			kunit_err(test, "expect free but is %s at page index %d\n",
 				  list_empty(page_to_lru(alloc->pages[i])) ?
 				  "alloc" : "lru", i);
-			binder_alloc_test_failures++;
+			failures++;
 		}
 	}
+
+	return failures;
 }
 
-static void binder_alloc_test_alloc_free(struct kunit *test,
+/* Executes one full test run for the given test case. */
+static bool binder_alloc_test_alloc_free(struct kunit *test,
 					 struct binder_alloc *alloc,
-					 size_t *sizes, int *seq, size_t end)
+					 struct binder_alloc_test_case_info *tc,
+					 size_t end)
 {
+	size_t pages = PAGE_ALIGN(end) / PAGE_SIZE;
 	struct binder_buffer *buffers[BUFFER_NUM];
-
-	binder_alloc_test_alloc_buf(test, alloc, buffers, sizes, seq);
-	binder_alloc_test_free_buf(test, alloc, buffers, sizes, seq, end);
+	unsigned long failures;
+	bool failed = false;
+
+	failures = binder_alloc_test_alloc_buf(test, alloc, buffers,
+					       tc->buffer_sizes,
+					       tc->free_sequence);
+	failed = failed || failures;
+	KUNIT_EXPECT_EQ_MSG(test, failures, 0,
+			    "Initial allocation failed: %lu/%u buffers with errors",
+			    failures, BUFFER_NUM);
+
+	failures = binder_alloc_test_free_buf(test, alloc, buffers,
+					      tc->buffer_sizes,
+					      tc->free_sequence, end);
+	failed = failed || failures;
+	KUNIT_EXPECT_EQ_MSG(test, failures, 0,
+			    "Initial buffers not freed correctly: %lu/%lu pages not on lru list",
+			    failures, pages);
 
 	/* Allocate from lru. */
-	binder_alloc_test_alloc_buf(test, alloc, buffers, sizes, seq);
-	if (list_lru_count(alloc->freelist))
-		kunit_err(test, "lru list should be empty but is not\n");
-
-	binder_alloc_test_free_buf(test, alloc, buffers, sizes, seq, end);
-	binder_alloc_test_free_page(test, alloc);
+	failures = binder_alloc_test_alloc_buf(test, alloc, buffers,
+					       tc->buffer_sizes,
+					       tc->free_sequence);
+	failed = failed || failures;
+	KUNIT_EXPECT_EQ_MSG(test, failures, 0,
+			    "Reallocation failed: %lu/%u buffers with errors",
+			    failures, BUFFER_NUM);
+
+	failures = list_lru_count(alloc->freelist);
+	failed = failed || failures;
+	KUNIT_EXPECT_EQ_MSG(test, failures, 0,
+			    "lru list should be empty after reallocation but still has %lu pages",
+			    failures);
+
+	failures = binder_alloc_test_free_buf(test, alloc, buffers,
+					      tc->buffer_sizes,
+					      tc->free_sequence, end);
+	failed = failed || failures;
+	KUNIT_EXPECT_EQ_MSG(test, failures, 0,
+			    "Reallocated buffers not freed correctly: %lu/%lu pages not on lru list",
+			    failures, pages);
+
+	failures = binder_alloc_test_free_page(test, alloc);
+	failed = failed || failures;
+	KUNIT_EXPECT_EQ_MSG(test, failures, 0,
+			    "Failed to clean up allocated pages: %lu/%lu pages still installed",
+			    failures, (alloc->buffer_size / PAGE_SIZE));
+
+	return failed;
 }
 
 static bool is_dup(int *seq, int index, int val)
@@ -213,24 +300,44 @@ static bool is_dup(int *seq, int index, int val)
 
 /* Generate BUFFER_NUM factorial free orders. */
 static void permute_frees(struct kunit *test, struct binder_alloc *alloc,
-			  size_t *sizes, int *seq, int index, size_t end)
+			  struct binder_alloc_test_case_info *tc,
+			  unsigned long *runs, unsigned long *failures,
+			  int index, size_t end)
 {
+	bool case_failed;
 	int i;
 
 	if (index == BUFFER_NUM) {
-		binder_alloc_test_alloc_free(test, alloc, sizes, seq, end);
+		char freeseq_buf[FREESEQ_BUFLEN];
+
+		case_failed = binder_alloc_test_alloc_free(test, alloc, tc, end);
+		*runs += 1;
+		*failures += case_failed;
+
+		if (case_failed || PRINT_ALL_CASES) {
+			stringify_free_seq(test, tc->free_sequence, freeseq_buf,
+					   FREESEQ_BUFLEN);
+			kunit_err(test, "case %zd: [%s] | %s - %s - %s", *runs,
+				  case_failed ? "FAILED" : "PASSED",
+				  tc->front_pages ? "front" : "back ",
+				  tc->alignments, freeseq_buf);
+		}
+
 		return;
 	}
 	for (i = 0; i < BUFFER_NUM; i++) {
-		if (is_dup(seq, index, i))
+		if (is_dup(tc->free_sequence, index, i))
 			continue;
-		seq[index] = i;
-		permute_frees(test, alloc, sizes, seq, index + 1, end);
+		tc->free_sequence[index] = i;
+		permute_frees(test, alloc, tc, runs, failures, index + 1, end);
 	}
 }
 
-static void gen_buf_sizes(struct kunit *test, struct binder_alloc *alloc,
-			  size_t *end_offset)
+static void gen_buf_sizes(struct kunit *test,
+			  struct binder_alloc *alloc,
+			  struct binder_alloc_test_case_info *tc,
+			  size_t *end_offset, unsigned long *runs,
+			  unsigned long *failures)
 {
 	size_t last_offset, offset = 0;
 	size_t front_sizes[BUFFER_NUM];
@@ -238,31 +345,45 @@ static void gen_buf_sizes(struct kunit *test, struct binder_alloc *alloc,
 	int seq[BUFFER_NUM] = {0};
 	int i;
 
+	tc->free_sequence = seq;
 	for (i = 0; i < BUFFER_NUM; i++) {
 		last_offset = offset;
 		offset = end_offset[i];
 		front_sizes[i] = offset - last_offset;
 		back_sizes[BUFFER_NUM - i - 1] = front_sizes[i];
 	}
+	back_sizes[0] += alloc->buffer_size - end_offset[BUFFER_NUM - 1];
+
 	/*
 	 * Buffers share the first or last few pages.
 	 * Only BUFFER_NUM - 1 buffer sizes are adjustable since
 	 * we need one giant buffer before getting to the last page.
 	 */
-	back_sizes[0] += alloc->buffer_size - end_offset[BUFFER_NUM - 1];
-	permute_frees(test, alloc, front_sizes, seq, 0,
+	tc->front_pages = true;
+	tc->buffer_sizes = front_sizes;
+	permute_frees(test, alloc, tc, runs, failures, 0,
 		      end_offset[BUFFER_NUM - 1]);
-	permute_frees(test, alloc, back_sizes, seq, 0, alloc->buffer_size);
+
+	tc->front_pages = false;
+	tc->buffer_sizes = back_sizes;
+	permute_frees(test, alloc, tc, runs, failures, 0, alloc->buffer_size);
 }
 
 static void gen_buf_offsets(struct kunit *test, struct binder_alloc *alloc,
-			    size_t *end_offset, int index)
+			    size_t *end_offset, int *alignments,
+			    unsigned long *runs, unsigned long *failures,
+			    int index)
 {
 	size_t end, prev;
 	int align;
 
 	if (index == BUFFER_NUM) {
-		gen_buf_sizes(test, alloc, end_offset);
+		struct binder_alloc_test_case_info tc = {0};
+
+		stringify_alignments(test, alignments, tc.alignments,
+				     ALIGNMENTS_BUFLEN);
+
+		gen_buf_sizes(test, alloc, &tc, end_offset, runs, failures);
 		return;
 	}
 	prev = index == 0 ? 0 : end_offset[index - 1];
@@ -276,7 +397,9 @@ static void gen_buf_offsets(struct kunit *test, struct binder_alloc *alloc,
 		else
 			end += BUFFER_MIN_SIZE;
 		end_offset[index] = end;
-		gen_buf_offsets(test, alloc, end_offset, index + 1);
+		alignments[index] = align;
+		gen_buf_offsets(test, alloc, end_offset, alignments, runs,
+				failures, index + 1);
 	}
 }
 
@@ -327,10 +450,15 @@ static void binder_alloc_exhaustive_test(struct kunit *test)
 {
 	struct binder_alloc_test *priv = test->priv;
 	size_t end_offset[BUFFER_NUM];
+	int alignments[BUFFER_NUM];
+	unsigned long failures = 0;
+	unsigned long runs = 0;
 
-	gen_buf_offsets(test, &priv->alloc, end_offset, 0);
+	gen_buf_offsets(test, &priv->alloc, end_offset, alignments, &runs,
+			&failures, 0);
 
-	KUNIT_EXPECT_EQ(test, binder_alloc_test_failures, 0);
+	KUNIT_EXPECT_EQ(test, runs, TOTAL_EXHAUSTIVE_CASES);
+	KUNIT_EXPECT_EQ(test, failures, 0);
 }
 
 /* ===== End test cases ===== */
-- 
2.50.0.727.gbf7dc18ff4-goog
Re: [PATCH 5/5] binder: encapsulate individual alloc test cases
Posted by kernel test robot 3 months, 1 week ago
Hi Tiffany,

kernel test robot noticed the following build warnings:

[auto build test WARNING on staging/staging-testing]
[also build test WARNING on staging/staging-next staging/staging-linus shuah-kselftest/kunit shuah-kselftest/kunit-fixes linus/master v6.16-rc3 next-20250627]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Tiffany-Yang/binder-Fix-selftest-page-indexing/20250628-044044
base:   staging/staging-testing
patch link:    https://lore.kernel.org/r/20250627203748.881022-6-ynaffit%40google.com
patch subject: [PATCH 5/5] binder: encapsulate individual alloc test cases
config: i386-buildonly-randconfig-001-20250628 (https://download.01.org/0day-ci/archive/20250628/202506281959.hfOTIUjS-lkp@intel.com/config)
compiler: clang version 20.1.7 (https://github.com/llvm/llvm-project 6146a88f60492b520a36f8f8f3231e15f3cc6082)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250628/202506281959.hfOTIUjS-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506281959.hfOTIUjS-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/android/tests/binder_alloc_kunit.c:256:18: warning: format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat]
     255 |                             "Initial buffers not freed correctly: %lu/%lu pages not on lru list",
         |                                                                       ~~~
         |                                                                       %zu
     256 |                             failures, pages);
         |                                       ^~~~~
   include/kunit/test.h:987:11: note: expanded from macro 'KUNIT_EXPECT_EQ_MSG'
     986 |                                    fmt,                                        \
         |                                    ~~~
     987 |                                     ##__VA_ARGS__)
         |                                       ^~~~~~~~~~~
   include/kunit/test.h:823:11: note: expanded from macro 'KUNIT_BINARY_INT_ASSERTION'
     822 |                                     fmt,                                       \
         |                                     ~~~
     823 |                                     ##__VA_ARGS__)
         |                                       ^~~~~~~~~~~
   include/kunit/test.h:807:11: note: expanded from macro 'KUNIT_BASE_BINARY_ASSERTION'
     806 |                       fmt,                                                     \
         |                       ~~~
     807 |                       ##__VA_ARGS__);                                          \
         |                         ^~~~~~~~~~~
   include/kunit/test.h:689:11: note: expanded from macro '_KUNIT_FAILED'
     688 |                                     fmt,                                       \
         |                                     ~~~
     689 |                                     ##__VA_ARGS__);                            \
         |                                       ^~~~~~~~~~~
   drivers/android/tests/binder_alloc_kunit.c:279:18: warning: format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat]
     278 |                             "Reallocated buffers not freed correctly: %lu/%lu pages not on lru list",
         |                                                                           ~~~
         |                                                                           %zu
     279 |                             failures, pages);
         |                                       ^~~~~
   include/kunit/test.h:987:11: note: expanded from macro 'KUNIT_EXPECT_EQ_MSG'
     986 |                                    fmt,                                        \
         |                                    ~~~
     987 |                                     ##__VA_ARGS__)
         |                                       ^~~~~~~~~~~
   include/kunit/test.h:823:11: note: expanded from macro 'KUNIT_BINARY_INT_ASSERTION'
     822 |                                     fmt,                                       \
         |                                     ~~~
     823 |                                     ##__VA_ARGS__)
         |                                       ^~~~~~~~~~~
   include/kunit/test.h:807:11: note: expanded from macro 'KUNIT_BASE_BINARY_ASSERTION'
     806 |                       fmt,                                                     \
         |                       ~~~
     807 |                       ##__VA_ARGS__);                                          \
         |                         ^~~~~~~~~~~
   include/kunit/test.h:689:11: note: expanded from macro '_KUNIT_FAILED'
     688 |                                     fmt,                                       \
         |                                     ~~~
     689 |                                     ##__VA_ARGS__);                            \
         |                                       ^~~~~~~~~~~
>> drivers/android/tests/binder_alloc_kunit.c:320:53: warning: format specifies type 'ssize_t' (aka 'int') but the argument has type 'unsigned long' [-Wformat]
     320 |                         kunit_err(test, "case %zd: [%s] | %s - %s - %s", *runs,
         |                                               ~~~                        ^~~~~
         |                                               %lu
   include/kunit/test.h:650:38: note: expanded from macro 'kunit_err'
     650 |         kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__)
         |                                      ~~~    ^~~~~~~~~~~
   include/kunit/test.h:616:21: note: expanded from macro 'kunit_printk'
     615 |         kunit_log(lvl, test, KUNIT_SUBTEST_INDENT "# %s: " fmt,         \
         |                                                            ~~~
     616 |                   (test)->name, ##__VA_ARGS__)
         |                                   ^~~~~~~~~~~
   include/kunit/test.h:609:21: note: expanded from macro 'kunit_log'
     609 |                 printk(lvl fmt, ##__VA_ARGS__);                         \
         |                            ~~~    ^~~~~~~~~~~
   include/linux/printk.h:507:60: note: expanded from macro 'printk'
     507 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
         |                                                     ~~~    ^~~~~~~~~~~
   include/linux/printk.h:479:19: note: expanded from macro 'printk_index_wrap'
     479 |                 _p_func(_fmt, ##__VA_ARGS__);                           \
         |                         ~~~~    ^~~~~~~~~~~
>> drivers/android/tests/binder_alloc_kunit.c:320:53: warning: format specifies type 'ssize_t' (aka 'int') but the argument has type 'unsigned long' [-Wformat]
     320 |                         kunit_err(test, "case %zd: [%s] | %s - %s - %s", *runs,
         |                                               ~~~                        ^~~~~
         |                                               %lu
   include/kunit/test.h:650:38: note: expanded from macro 'kunit_err'
     650 |         kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__)
         |                                      ~~~    ^~~~~~~~~~~
   include/kunit/test.h:616:21: note: expanded from macro 'kunit_printk'
     615 |         kunit_log(lvl, test, KUNIT_SUBTEST_INDENT "# %s: " fmt,         \
         |                                                            ~~~
     616 |                   (test)->name, ##__VA_ARGS__)
         |                                   ^~~~~~~~~~~
   include/kunit/test.h:611:8: note: expanded from macro 'kunit_log'
     610 |                 kunit_log_append((test_or_suite)->log,  fmt,            \
         |                                                         ~~~
     611 |                                  ##__VA_ARGS__);                        \
         |                                    ^~~~~~~~~~~
   4 warnings generated.


vim +256 drivers/android/tests/binder_alloc_kunit.c

   230	
   231	/* Executes one full test run for the given test case. */
   232	static bool binder_alloc_test_alloc_free(struct kunit *test,
   233						 struct binder_alloc *alloc,
   234						 struct binder_alloc_test_case_info *tc,
   235						 size_t end)
   236	{
   237		size_t pages = PAGE_ALIGN(end) / PAGE_SIZE;
   238		struct binder_buffer *buffers[BUFFER_NUM];
   239		unsigned long failures;
   240		bool failed = false;
   241	
   242		failures = binder_alloc_test_alloc_buf(test, alloc, buffers,
   243						       tc->buffer_sizes,
   244						       tc->free_sequence);
   245		failed = failed || failures;
   246		KUNIT_EXPECT_EQ_MSG(test, failures, 0,
   247				    "Initial allocation failed: %lu/%u buffers with errors",
   248				    failures, BUFFER_NUM);
   249	
   250		failures = binder_alloc_test_free_buf(test, alloc, buffers,
   251						      tc->buffer_sizes,
   252						      tc->free_sequence, end);
   253		failed = failed || failures;
   254		KUNIT_EXPECT_EQ_MSG(test, failures, 0,
   255				    "Initial buffers not freed correctly: %lu/%lu pages not on lru list",
 > 256				    failures, pages);
   257	
   258		/* Allocate from lru. */
   259		failures = binder_alloc_test_alloc_buf(test, alloc, buffers,
   260						       tc->buffer_sizes,
   261						       tc->free_sequence);
   262		failed = failed || failures;
   263		KUNIT_EXPECT_EQ_MSG(test, failures, 0,
   264				    "Reallocation failed: %lu/%u buffers with errors",
   265				    failures, BUFFER_NUM);
   266	
   267		failures = list_lru_count(alloc->freelist);
   268		failed = failed || failures;
   269		KUNIT_EXPECT_EQ_MSG(test, failures, 0,
   270				    "lru list should be empty after reallocation but still has %lu pages",
   271				    failures);
   272	
   273		failures = binder_alloc_test_free_buf(test, alloc, buffers,
   274						      tc->buffer_sizes,
   275						      tc->free_sequence, end);
   276		failed = failed || failures;
   277		KUNIT_EXPECT_EQ_MSG(test, failures, 0,
   278				    "Reallocated buffers not freed correctly: %lu/%lu pages not on lru list",
   279				    failures, pages);
   280	
   281		failures = binder_alloc_test_free_page(test, alloc);
   282		failed = failed || failures;
   283		KUNIT_EXPECT_EQ_MSG(test, failures, 0,
   284				    "Failed to clean up allocated pages: %lu/%lu pages still installed",
   285				    failures, (alloc->buffer_size / PAGE_SIZE));
   286	
   287		return failed;
   288	}
   289	
   290	static bool is_dup(int *seq, int index, int val)
   291	{
   292		int i;
   293	
   294		for (i = 0; i < index; i++) {
   295			if (seq[i] == val)
   296				return true;
   297		}
   298		return false;
   299	}
   300	
   301	/* Generate BUFFER_NUM factorial free orders. */
   302	static void permute_frees(struct kunit *test, struct binder_alloc *alloc,
   303				  struct binder_alloc_test_case_info *tc,
   304				  unsigned long *runs, unsigned long *failures,
   305				  int index, size_t end)
   306	{
   307		bool case_failed;
   308		int i;
   309	
   310		if (index == BUFFER_NUM) {
   311			char freeseq_buf[FREESEQ_BUFLEN];
   312	
   313			case_failed = binder_alloc_test_alloc_free(test, alloc, tc, end);
   314			*runs += 1;
   315			*failures += case_failed;
   316	
   317			if (case_failed || PRINT_ALL_CASES) {
   318				stringify_free_seq(test, tc->free_sequence, freeseq_buf,
   319						   FREESEQ_BUFLEN);
 > 320				kunit_err(test, "case %zd: [%s] | %s - %s - %s", *runs,
   321					  case_failed ? "FAILED" : "PASSED",
   322					  tc->front_pages ? "front" : "back ",
   323					  tc->alignments, freeseq_buf);
   324			}
   325	
   326			return;
   327		}
   328		for (i = 0; i < BUFFER_NUM; i++) {
   329			if (is_dup(tc->free_sequence, index, i))
   330				continue;
   331			tc->free_sequence[index] = i;
   332			permute_frees(test, alloc, tc, runs, failures, index + 1, end);
   333		}
   334	}
   335	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki