1 // SPDX-License-Identifier: GPL-2.0
2 // Unit tests for property entries API
3 //
4 // Copyright 2019 Google LLC.
5 
6 #include <kunit/test.h>
7 #include <linux/property.h>
8 #include <linux/types.h>
9 
10 static void pe_test_uints(struct kunit *test)
11 {
12 	static const struct property_entry entries[] = {
13 		PROPERTY_ENTRY_U8("prop-u8", 8),
14 		PROPERTY_ENTRY_U16("prop-u16", 16),
15 		PROPERTY_ENTRY_U32("prop-u32", 32),
16 		PROPERTY_ENTRY_U64("prop-u64", 64),
17 		{ }
18 	};
19 
20 	struct fwnode_handle *node;
21 	u8 val_u8, array_u8[2];
22 	u16 val_u16, array_u16[2];
23 	u32 val_u32, array_u32[2];
24 	u64 val_u64, array_u64[2];
25 	int error;
26 
27 	node = fwnode_create_software_node(entries, NULL);
28 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node);
29 
30 	error = fwnode_property_read_u8(node, "prop-u8", &val_u8);
31 	KUNIT_EXPECT_EQ(test, error, 0);
32 	KUNIT_EXPECT_EQ(test, (int)val_u8, 8);
33 
34 	error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 1);
35 	KUNIT_EXPECT_EQ(test, error, 0);
36 	KUNIT_EXPECT_EQ(test, (int)array_u8[0], 8);
37 
38 	error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 2);
39 	KUNIT_EXPECT_NE(test, error, 0);
40 
41 	error = fwnode_property_read_u8(node, "no-prop-u8", &val_u8);
42 	KUNIT_EXPECT_NE(test, error, 0);
43 
44 	error = fwnode_property_read_u8_array(node, "no-prop-u8", array_u8, 1);
45 	KUNIT_EXPECT_NE(test, error, 0);
46 
47 	error = fwnode_property_read_u16(node, "prop-u16", &val_u16);
48 	KUNIT_EXPECT_EQ(test, error, 0);
49 	KUNIT_EXPECT_EQ(test, (int)val_u16, 16);
50 
51 	error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 1);
52 	KUNIT_EXPECT_EQ(test, error, 0);
53 	KUNIT_EXPECT_EQ(test, (int)array_u16[0], 16);
54 
55 	error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 2);
56 	KUNIT_EXPECT_NE(test, error, 0);
57 
58 	error = fwnode_property_read_u16(node, "no-prop-u16", &val_u16);
59 	KUNIT_EXPECT_NE(test, error, 0);
60 
61 	error = fwnode_property_read_u16_array(node, "no-prop-u16", array_u16, 1);
62 	KUNIT_EXPECT_NE(test, error, 0);
63 
64 	error = fwnode_property_read_u32(node, "prop-u32", &val_u32);
65 	KUNIT_EXPECT_EQ(test, error, 0);
66 	KUNIT_EXPECT_EQ(test, (int)val_u32, 32);
67 
68 	error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 1);
69 	KUNIT_EXPECT_EQ(test, error, 0);
70 	KUNIT_EXPECT_EQ(test, (int)array_u32[0], 32);
71 
72 	error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 2);
73 	KUNIT_EXPECT_NE(test, error, 0);
74 
75 	error = fwnode_property_read_u32(node, "no-prop-u32", &val_u32);
76 	KUNIT_EXPECT_NE(test, error, 0);
77 
78 	error = fwnode_property_read_u32_array(node, "no-prop-u32", array_u32, 1);
79 	KUNIT_EXPECT_NE(test, error, 0);
80 
81 	error = fwnode_property_read_u64(node, "prop-u64", &val_u64);
82 	KUNIT_EXPECT_EQ(test, error, 0);
83 	KUNIT_EXPECT_EQ(test, (int)val_u64, 64);
84 
85 	error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 1);
86 	KUNIT_EXPECT_EQ(test, error, 0);
87 	KUNIT_EXPECT_EQ(test, (int)array_u64[0], 64);
88 
89 	error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 2);
90 	KUNIT_EXPECT_NE(test, error, 0);
91 
92 	error = fwnode_property_read_u64(node, "no-prop-u64", &val_u64);
93 	KUNIT_EXPECT_NE(test, error, 0);
94 
95 	error = fwnode_property_read_u64_array(node, "no-prop-u64", array_u64, 1);
96 	KUNIT_EXPECT_NE(test, error, 0);
97 
98 	fwnode_remove_software_node(node);
99 }
100 
101 static void pe_test_uint_arrays(struct kunit *test)
102 {
103 	static const u8 a_u8[16] = { 8, 9 };
104 	static const u16 a_u16[16] = { 16, 17 };
105 	static const u32 a_u32[16] = { 32, 33 };
106 	static const u64 a_u64[16] = { 64, 65 };
107 	static const struct property_entry entries[] = {
108 		PROPERTY_ENTRY_U8_ARRAY("prop-u8", a_u8),
109 		PROPERTY_ENTRY_U16_ARRAY("prop-u16", a_u16),
110 		PROPERTY_ENTRY_U32_ARRAY("prop-u32", a_u32),
111 		PROPERTY_ENTRY_U64_ARRAY("prop-u64", a_u64),
112 		{ }
113 	};
114 
115 	struct fwnode_handle *node;
116 	u8 val_u8, array_u8[32];
117 	u16 val_u16, array_u16[32];
118 	u32 val_u32, array_u32[32];
119 	u64 val_u64, array_u64[32];
120 	int error;
121 
122 	node = fwnode_create_software_node(entries, NULL);
123 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node);
124 
125 	error = fwnode_property_read_u8(node, "prop-u8", &val_u8);
126 	KUNIT_EXPECT_EQ(test, error, 0);
127 	KUNIT_EXPECT_EQ(test, (int)val_u8, 8);
128 
129 	error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 1);
130 	KUNIT_EXPECT_EQ(test, error, 0);
131 	KUNIT_EXPECT_EQ(test, (int)array_u8[0], 8);
132 
133 	error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 2);
134 	KUNIT_EXPECT_EQ(test, error, 0);
135 	KUNIT_EXPECT_EQ(test, (int)array_u8[0], 8);
136 	KUNIT_EXPECT_EQ(test, (int)array_u8[1], 9);
137 
138 	error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 17);
139 	KUNIT_EXPECT_NE(test, error, 0);
140 
141 	error = fwnode_property_read_u8(node, "no-prop-u8", &val_u8);
142 	KUNIT_EXPECT_NE(test, error, 0);
143 
144 	error = fwnode_property_read_u8_array(node, "no-prop-u8", array_u8, 1);
145 	KUNIT_EXPECT_NE(test, error, 0);
146 
147 	error = fwnode_property_read_u16(node, "prop-u16", &val_u16);
148 	KUNIT_EXPECT_EQ(test, error, 0);
149 	KUNIT_EXPECT_EQ(test, (int)val_u16, 16);
150 
151 	error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 1);
152 	KUNIT_EXPECT_EQ(test, error, 0);
153 	KUNIT_EXPECT_EQ(test, (int)array_u16[0], 16);
154 
155 	error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 2);
156 	KUNIT_EXPECT_EQ(test, error, 0);
157 	KUNIT_EXPECT_EQ(test, (int)array_u16[0], 16);
158 	KUNIT_EXPECT_EQ(test, (int)array_u16[1], 17);
159 
160 	error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 17);
161 	KUNIT_EXPECT_NE(test, error, 0);
162 
163 	error = fwnode_property_read_u16(node, "no-prop-u16", &val_u16);
164 	KUNIT_EXPECT_NE(test, error, 0);
165 
166 	error = fwnode_property_read_u16_array(node, "no-prop-u16", array_u16, 1);
167 	KUNIT_EXPECT_NE(test, error, 0);
168 
169 	error = fwnode_property_read_u32(node, "prop-u32", &val_u32);
170 	KUNIT_EXPECT_EQ(test, error, 0);
171 	KUNIT_EXPECT_EQ(test, (int)val_u32, 32);
172 
173 	error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 1);
174 	KUNIT_EXPECT_EQ(test, error, 0);
175 	KUNIT_EXPECT_EQ(test, (int)array_u32[0], 32);
176 
177 	error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 2);
178 	KUNIT_EXPECT_EQ(test, error, 0);
179 	KUNIT_EXPECT_EQ(test, (int)array_u32[0], 32);
180 	KUNIT_EXPECT_EQ(test, (int)array_u32[1], 33);
181 
182 	error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 17);
183 	KUNIT_EXPECT_NE(test, error, 0);
184 
185 	error = fwnode_property_read_u32(node, "no-prop-u32", &val_u32);
186 	KUNIT_EXPECT_NE(test, error, 0);
187 
188 	error = fwnode_property_read_u32_array(node, "no-prop-u32", array_u32, 1);
189 	KUNIT_EXPECT_NE(test, error, 0);
190 
191 	error = fwnode_property_read_u64(node, "prop-u64", &val_u64);
192 	KUNIT_EXPECT_EQ(test, error, 0);
193 	KUNIT_EXPECT_EQ(test, (int)val_u64, 64);
194 
195 	error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 1);
196 	KUNIT_EXPECT_EQ(test, error, 0);
197 	KUNIT_EXPECT_EQ(test, (int)array_u64[0], 64);
198 
199 	error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 2);
200 	KUNIT_EXPECT_EQ(test, error, 0);
201 	KUNIT_EXPECT_EQ(test, (int)array_u64[0], 64);
202 	KUNIT_EXPECT_EQ(test, (int)array_u64[1], 65);
203 
204 	error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 17);
205 	KUNIT_EXPECT_NE(test, error, 0);
206 
207 	error = fwnode_property_read_u64(node, "no-prop-u64", &val_u64);
208 	KUNIT_EXPECT_NE(test, error, 0);
209 
210 	error = fwnode_property_read_u64_array(node, "no-prop-u64", array_u64, 1);
211 	KUNIT_EXPECT_NE(test, error, 0);
212 
213 	fwnode_remove_software_node(node);
214 }
215 
216 static void pe_test_strings(struct kunit *test)
217 {
218 	static const char *strings[] = {
219 		"string-a",
220 		"string-b",
221 	};
222 
223 	static const struct property_entry entries[] = {
224 		PROPERTY_ENTRY_STRING("str", "single"),
225 		PROPERTY_ENTRY_STRING("empty", ""),
226 		PROPERTY_ENTRY_STRING_ARRAY("strs", strings),
227 		{ }
228 	};
229 
230 	struct fwnode_handle *node;
231 	const char *str;
232 	const char *strs[10];
233 	int error;
234 
235 	node = fwnode_create_software_node(entries, NULL);
236 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node);
237 
238 	error = fwnode_property_read_string(node, "str", &str);
239 	KUNIT_EXPECT_EQ(test, error, 0);
240 	KUNIT_EXPECT_STREQ(test, str, "single");
241 
242 	error = fwnode_property_read_string_array(node, "str", strs, 1);
243 	KUNIT_EXPECT_EQ(test, error, 1);
244 	KUNIT_EXPECT_STREQ(test, strs[0], "single");
245 
246 	/* asking for more data returns what we have */
247 	error = fwnode_property_read_string_array(node, "str", strs, 2);
248 	KUNIT_EXPECT_EQ(test, error, 1);
249 	KUNIT_EXPECT_STREQ(test, strs[0], "single");
250 
251 	error = fwnode_property_read_string(node, "no-str", &str);
252 	KUNIT_EXPECT_NE(test, error, 0);
253 
254 	error = fwnode_property_read_string_array(node, "no-str", strs, 1);
255 	KUNIT_EXPECT_LT(test, error, 0);
256 
257 	error = fwnode_property_read_string(node, "empty", &str);
258 	KUNIT_EXPECT_EQ(test, error, 0);
259 	KUNIT_EXPECT_STREQ(test, str, "");
260 
261 	error = fwnode_property_read_string_array(node, "strs", strs, 3);
262 	KUNIT_EXPECT_EQ(test, error, 2);
263 	KUNIT_EXPECT_STREQ(test, strs[0], "string-a");
264 	KUNIT_EXPECT_STREQ(test, strs[1], "string-b");
265 
266 	error = fwnode_property_read_string_array(node, "strs", strs, 1);
267 	KUNIT_EXPECT_EQ(test, error, 1);
268 	KUNIT_EXPECT_STREQ(test, strs[0], "string-a");
269 
270 	/* NULL argument -> returns size */
271 	error = fwnode_property_read_string_array(node, "strs", NULL, 0);
272 	KUNIT_EXPECT_EQ(test, error, 2);
273 
274 	/* accessing array as single value */
275 	error = fwnode_property_read_string(node, "strs", &str);
276 	KUNIT_EXPECT_EQ(test, error, 0);
277 	KUNIT_EXPECT_STREQ(test, str, "string-a");
278 
279 	fwnode_remove_software_node(node);
280 }
281 
282 static void pe_test_bool(struct kunit *test)
283 {
284 	static const struct property_entry entries[] = {
285 		PROPERTY_ENTRY_BOOL("prop"),
286 		{ }
287 	};
288 
289 	struct fwnode_handle *node;
290 
291 	node = fwnode_create_software_node(entries, NULL);
292 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node);
293 
294 	KUNIT_EXPECT_TRUE(test, fwnode_property_read_bool(node, "prop"));
295 	KUNIT_EXPECT_FALSE(test, fwnode_property_read_bool(node, "not-prop"));
296 
297 	fwnode_remove_software_node(node);
298 }
299 
300 /* Verifies that small U8 array is stored inline when property is copied */
301 static void pe_test_move_inline_u8(struct kunit *test)
302 {
303 	static const u8 u8_array_small[8] = { 1, 2, 3, 4 };
304 	static const u8 u8_array_big[128] = { 5, 6, 7, 8 };
305 	static const struct property_entry entries[] = {
306 		PROPERTY_ENTRY_U8_ARRAY("small", u8_array_small),
307 		PROPERTY_ENTRY_U8_ARRAY("big", u8_array_big),
308 		{ }
309 	};
310 
311 	struct property_entry *copy;
312 	const u8 *data_ptr;
313 
314 	copy = property_entries_dup(entries);
315 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, copy);
316 
317 	KUNIT_EXPECT_TRUE(test, copy[0].is_inline);
318 	data_ptr = (u8 *)&copy[0].value;
319 	KUNIT_EXPECT_EQ(test, (int)data_ptr[0], 1);
320 	KUNIT_EXPECT_EQ(test, (int)data_ptr[1], 2);
321 
322 	KUNIT_EXPECT_FALSE(test, copy[1].is_inline);
323 	data_ptr = copy[1].pointer;
324 	KUNIT_EXPECT_EQ(test, (int)data_ptr[0], 5);
325 	KUNIT_EXPECT_EQ(test, (int)data_ptr[1], 6);
326 
327 	property_entries_free(copy);
328 }
329 
330 /* Verifies that single string array is stored inline when property is copied */
331 static void pe_test_move_inline_str(struct kunit *test)
332 {
333 	static char *str_array_small[] = { "a" };
334 	static char *str_array_big[] = { "b", "c", "d", "e" };
335 	static char *str_array_small_empty[] = { "" };
336 	static struct property_entry entries[] = {
337 		PROPERTY_ENTRY_STRING_ARRAY("small", str_array_small),
338 		PROPERTY_ENTRY_STRING_ARRAY("big", str_array_big),
339 		PROPERTY_ENTRY_STRING_ARRAY("small-empty", str_array_small_empty),
340 		{ }
341 	};
342 
343 	struct property_entry *copy;
344 	const char * const *data_ptr;
345 
346 	copy = property_entries_dup(entries);
347 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, copy);
348 
349 	KUNIT_EXPECT_TRUE(test, copy[0].is_inline);
350 	KUNIT_EXPECT_STREQ(test, copy[0].value.str[0], "a");
351 
352 	KUNIT_EXPECT_FALSE(test, copy[1].is_inline);
353 	data_ptr = copy[1].pointer;
354 	KUNIT_EXPECT_STREQ(test, data_ptr[0], "b");
355 	KUNIT_EXPECT_STREQ(test, data_ptr[1], "c");
356 
357 	KUNIT_EXPECT_TRUE(test, copy[2].is_inline);
358 	KUNIT_EXPECT_STREQ(test, copy[2].value.str[0], "");
359 
360 	property_entries_free(copy);
361 }
362 
363 /* Handling of reference properties */
364 static void pe_test_reference(struct kunit *test)
365 {
366 	static const struct software_node nodes[] = {
367 		{ .name = "1", },
368 		{ .name = "2", },
369 		{ }
370 	};
371 
372 	static const struct software_node_ref_args refs[] = {
373 		{
374 			.node = &nodes[0],
375 			.nargs = 0,
376 		},
377 		{
378 			.node = &nodes[1],
379 			.nargs = 2,
380 			.args = { 3, 4 },
381 		},
382 	};
383 
384 	const struct property_entry entries[] = {
385 		PROPERTY_ENTRY_REF("ref-1", &nodes[0]),
386 		PROPERTY_ENTRY_REF("ref-2", &nodes[1], 1, 2),
387 		PROPERTY_ENTRY_REF_ARRAY("ref-3", refs),
388 		{ }
389 	};
390 
391 	struct fwnode_handle *node;
392 	struct fwnode_reference_args ref;
393 	int error;
394 
395 	error = software_node_register_nodes(nodes);
396 	KUNIT_ASSERT_EQ(test, error, 0);
397 
398 	node = fwnode_create_software_node(entries, NULL);
399 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node);
400 
401 	error = fwnode_property_get_reference_args(node, "ref-1", NULL,
402 						   0, 0, &ref);
403 	KUNIT_ASSERT_EQ(test, error, 0);
404 	KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[0]);
405 	KUNIT_EXPECT_EQ(test, ref.nargs, 0U);
406 
407 	/* wrong index */
408 	error = fwnode_property_get_reference_args(node, "ref-1", NULL,
409 						   0, 1, &ref);
410 	KUNIT_EXPECT_NE(test, error, 0);
411 
412 	error = fwnode_property_get_reference_args(node, "ref-2", NULL,
413 						   1, 0, &ref);
414 	KUNIT_ASSERT_EQ(test, error, 0);
415 	KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[1]);
416 	KUNIT_EXPECT_EQ(test, ref.nargs, 1U);
417 	KUNIT_EXPECT_EQ(test, ref.args[0], 1LLU);
418 
419 	/* asking for more args, padded with zero data */
420 	error = fwnode_property_get_reference_args(node, "ref-2", NULL,
421 						   3, 0, &ref);
422 	KUNIT_ASSERT_EQ(test, error, 0);
423 	KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[1]);
424 	KUNIT_EXPECT_EQ(test, ref.nargs, 3U);
425 	KUNIT_EXPECT_EQ(test, ref.args[0], 1LLU);
426 	KUNIT_EXPECT_EQ(test, ref.args[1], 2LLU);
427 	KUNIT_EXPECT_EQ(test, ref.args[2], 0LLU);
428 
429 	/* wrong index */
430 	error = fwnode_property_get_reference_args(node, "ref-2", NULL,
431 						   2, 1, &ref);
432 	KUNIT_EXPECT_NE(test, error, 0);
433 
434 	/* array of references */
435 	error = fwnode_property_get_reference_args(node, "ref-3", NULL,
436 						   0, 0, &ref);
437 	KUNIT_ASSERT_EQ(test, error, 0);
438 	KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[0]);
439 	KUNIT_EXPECT_EQ(test, ref.nargs, 0U);
440 
441 	/* second reference in the array */
442 	error = fwnode_property_get_reference_args(node, "ref-3", NULL,
443 						   2, 1, &ref);
444 	KUNIT_ASSERT_EQ(test, error, 0);
445 	KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[1]);
446 	KUNIT_EXPECT_EQ(test, ref.nargs, 2U);
447 	KUNIT_EXPECT_EQ(test, ref.args[0], 3LLU);
448 	KUNIT_EXPECT_EQ(test, ref.args[1], 4LLU);
449 
450 	/* wrong index */
451 	error = fwnode_property_get_reference_args(node, "ref-1", NULL,
452 						   0, 2, &ref);
453 	KUNIT_EXPECT_NE(test, error, 0);
454 
455 	fwnode_remove_software_node(node);
456 	software_node_unregister_nodes(nodes);
457 }
458 
459 static struct kunit_case property_entry_test_cases[] = {
460 	KUNIT_CASE(pe_test_uints),
461 	KUNIT_CASE(pe_test_uint_arrays),
462 	KUNIT_CASE(pe_test_strings),
463 	KUNIT_CASE(pe_test_bool),
464 	KUNIT_CASE(pe_test_move_inline_u8),
465 	KUNIT_CASE(pe_test_move_inline_str),
466 	KUNIT_CASE(pe_test_reference),
467 	{ }
468 };
469 
470 static struct kunit_suite property_entry_test_suite = {
471 	.name = "property-entry",
472 	.test_cases = property_entry_test_cases,
473 };
474 
475 kunit_test_suite(property_entry_test_suite);
476