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