xref: /linux/drivers/android/tests/binder_alloc_kunit.c (revision 5e024582f494c6ff5eb2bec5183fd1eb35462500)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test cases for binder allocator code
4  */
5 
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7 
8 #include <kunit/test.h>
9 #include <linux/anon_inodes.h>
10 #include <linux/err.h>
11 #include <linux/file.h>
12 #include <linux/fs.h>
13 #include <linux/mm.h>
14 #include <linux/mman.h>
15 #include <linux/sizes.h>
16 
17 #include "../binder_alloc.h"
18 #include "../binder_internal.h"
19 
20 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
21 
22 #define BINDER_MMAP_SIZE SZ_128K
23 
24 struct binder_alloc_test {
25 	struct binder_alloc alloc;
26 	struct list_lru binder_test_freelist;
27 	struct file *filp;
28 	unsigned long mmap_uaddr;
29 };
30 
31 static void binder_alloc_test_init_freelist(struct kunit *test)
32 {
33 	struct binder_alloc_test *priv = test->priv;
34 
35 	KUNIT_EXPECT_PTR_EQ(test, priv->alloc.freelist,
36 			    &priv->binder_test_freelist);
37 }
38 
39 static void binder_alloc_test_mmap(struct kunit *test)
40 {
41 	struct binder_alloc_test *priv = test->priv;
42 	struct binder_alloc *alloc = &priv->alloc;
43 	struct binder_buffer *buf;
44 	struct rb_node *n;
45 
46 	KUNIT_EXPECT_EQ(test, alloc->mapped, true);
47 	KUNIT_EXPECT_EQ(test, alloc->buffer_size, BINDER_MMAP_SIZE);
48 
49 	n = rb_first(&alloc->allocated_buffers);
50 	KUNIT_EXPECT_PTR_EQ(test, n, NULL);
51 
52 	n = rb_first(&alloc->free_buffers);
53 	buf = rb_entry(n, struct binder_buffer, rb_node);
54 	KUNIT_EXPECT_EQ(test, binder_alloc_buffer_size(alloc, buf),
55 			BINDER_MMAP_SIZE);
56 	KUNIT_EXPECT_TRUE(test, list_is_last(&buf->entry, &alloc->buffers));
57 }
58 
59 /* ===== End test cases ===== */
60 
61 static void binder_alloc_test_vma_close(struct vm_area_struct *vma)
62 {
63 	struct binder_alloc *alloc = vma->vm_private_data;
64 
65 	binder_alloc_vma_close(alloc);
66 }
67 
68 static const struct vm_operations_struct binder_alloc_test_vm_ops = {
69 	.close = binder_alloc_test_vma_close,
70 	.fault = binder_vm_fault,
71 };
72 
73 static int binder_alloc_test_mmap_handler(struct file *filp,
74 					  struct vm_area_struct *vma)
75 {
76 	struct binder_alloc *alloc = filp->private_data;
77 
78 	vm_flags_mod(vma, VM_DONTCOPY | VM_MIXEDMAP, VM_MAYWRITE);
79 
80 	vma->vm_ops = &binder_alloc_test_vm_ops;
81 	vma->vm_private_data = alloc;
82 
83 	return binder_alloc_mmap_handler(alloc, vma);
84 }
85 
86 static const struct file_operations binder_alloc_test_fops = {
87 	.mmap = binder_alloc_test_mmap_handler,
88 };
89 
90 static int binder_alloc_test_init(struct kunit *test)
91 {
92 	struct binder_alloc_test *priv;
93 	int ret;
94 
95 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
96 	if (!priv)
97 		return -ENOMEM;
98 	test->priv = priv;
99 
100 	ret = list_lru_init(&priv->binder_test_freelist);
101 	if (ret) {
102 		kunit_err(test, "Failed to initialize test freelist\n");
103 		return ret;
104 	}
105 
106 	/* __binder_alloc_init requires mm to be attached */
107 	ret = kunit_attach_mm();
108 	if (ret) {
109 		kunit_err(test, "Failed to attach mm\n");
110 		return ret;
111 	}
112 	__binder_alloc_init(&priv->alloc, &priv->binder_test_freelist);
113 
114 	priv->filp = anon_inode_getfile("binder_alloc_kunit",
115 					&binder_alloc_test_fops, &priv->alloc,
116 					O_RDWR | O_CLOEXEC);
117 	if (IS_ERR_OR_NULL(priv->filp)) {
118 		kunit_err(test, "Failed to open binder alloc test driver file\n");
119 		return priv->filp ? PTR_ERR(priv->filp) : -ENOMEM;
120 	}
121 
122 	priv->mmap_uaddr = kunit_vm_mmap(test, priv->filp, 0, BINDER_MMAP_SIZE,
123 					 PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
124 					 0);
125 	if (!priv->mmap_uaddr) {
126 		kunit_err(test, "Could not map the test's transaction memory\n");
127 		return -ENOMEM;
128 	}
129 
130 	return 0;
131 }
132 
133 static void binder_alloc_test_exit(struct kunit *test)
134 {
135 	struct binder_alloc_test *priv = test->priv;
136 
137 	/* Close the backing file to make sure binder_alloc_vma_close runs */
138 	if (!IS_ERR_OR_NULL(priv->filp))
139 		fput(priv->filp);
140 
141 	if (priv->alloc.mm)
142 		binder_alloc_deferred_release(&priv->alloc);
143 
144 	/* Make sure freelist is empty */
145 	KUNIT_EXPECT_EQ(test, list_lru_count(&priv->binder_test_freelist), 0);
146 	list_lru_destroy(&priv->binder_test_freelist);
147 }
148 
149 static struct kunit_case binder_alloc_test_cases[] = {
150 	KUNIT_CASE(binder_alloc_test_init_freelist),
151 	KUNIT_CASE(binder_alloc_test_mmap),
152 	{}
153 };
154 
155 static struct kunit_suite binder_alloc_test_suite = {
156 	.name = "binder_alloc",
157 	.test_cases = binder_alloc_test_cases,
158 	.init = binder_alloc_test_init,
159 	.exit = binder_alloc_test_exit,
160 };
161 
162 kunit_test_suite(binder_alloc_test_suite);
163 
164 MODULE_AUTHOR("Tiffany Yang <ynaffit@google.com>");
165 MODULE_DESCRIPTION("Binder Alloc KUnit tests");
166 MODULE_LICENSE("GPL");
167