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 *)©[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