Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

list: test: Test the klist structure

Add KUnit tests to the klist linked-list structure.
These perform testing for different variations of node add
and node delete in the klist data structure (<linux/klist.h>).

Limitation: Since we use a static global variable, and if
multiple instances of this test are run concurrently, the test may fail.

Signed-off-by: Sadiya Kazi <sadiyakazi@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Reviewed-by: David Gow <davidgow@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>

authored by

Sadiya Kazi and committed by
Shuah Khan
57b4f760 7232282d

+299 -1
+299 -1
lib/list-test.c
··· 8 8 #include <kunit/test.h> 9 9 10 10 #include <linux/list.h> 11 + #include <linux/klist.h> 11 12 12 13 struct list_test_struct { 13 14 int data; ··· 1200 1199 .test_cases = hlist_test_cases, 1201 1200 }; 1202 1201 1203 - kunit_test_suites(&list_test_module, &hlist_test_module); 1202 + 1203 + struct klist_test_struct { 1204 + int data; 1205 + struct klist klist; 1206 + struct klist_node klist_node; 1207 + }; 1208 + 1209 + static int node_count; 1210 + static struct klist_node *last_node; 1211 + 1212 + static void check_node(struct klist_node *node_ptr) 1213 + { 1214 + node_count++; 1215 + last_node = node_ptr; 1216 + } 1217 + 1218 + static void check_delete_node(struct klist_node *node_ptr) 1219 + { 1220 + node_count--; 1221 + last_node = node_ptr; 1222 + } 1223 + 1224 + static void klist_test_add_tail(struct kunit *test) 1225 + { 1226 + struct klist_node a, b; 1227 + struct klist mylist; 1228 + struct klist_iter i; 1229 + 1230 + node_count = 0; 1231 + klist_init(&mylist, &check_node, NULL); 1232 + 1233 + klist_add_tail(&a, &mylist); 1234 + KUNIT_EXPECT_EQ(test, node_count, 1); 1235 + KUNIT_EXPECT_PTR_EQ(test, last_node, &a); 1236 + 1237 + klist_add_tail(&b, &mylist); 1238 + KUNIT_EXPECT_EQ(test, node_count, 2); 1239 + KUNIT_EXPECT_PTR_EQ(test, last_node, &b); 1240 + 1241 + /* should be [list] -> a -> b */ 1242 + klist_iter_init(&mylist, &i); 1243 + 1244 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a); 1245 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b); 1246 + KUNIT_EXPECT_NULL(test, klist_next(&i)); 1247 + 1248 + klist_iter_exit(&i); 1249 + 1250 + } 1251 + 1252 + static void klist_test_add_head(struct kunit *test) 1253 + { 1254 + struct klist_node a, b; 1255 + struct klist mylist; 1256 + struct klist_iter i; 1257 + 1258 + node_count = 0; 1259 + klist_init(&mylist, &check_node, NULL); 1260 + 1261 + klist_add_head(&a, &mylist); 1262 + KUNIT_EXPECT_EQ(test, node_count, 1); 1263 + KUNIT_EXPECT_PTR_EQ(test, last_node, &a); 1264 + 1265 + klist_add_head(&b, &mylist); 1266 + KUNIT_EXPECT_EQ(test, node_count, 2); 1267 + KUNIT_EXPECT_PTR_EQ(test, last_node, &b); 1268 + 1269 + /* should be [list] -> b -> a */ 1270 + klist_iter_init(&mylist, &i); 1271 + 1272 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b); 1273 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a); 1274 + KUNIT_EXPECT_NULL(test, klist_next(&i)); 1275 + 1276 + klist_iter_exit(&i); 1277 + 1278 + } 1279 + 1280 + static void klist_test_add_behind(struct kunit *test) 1281 + { 1282 + struct klist_node a, b, c, d; 1283 + struct klist mylist; 1284 + struct klist_iter i; 1285 + 1286 + node_count = 0; 1287 + klist_init(&mylist, &check_node, NULL); 1288 + 1289 + klist_add_head(&a, &mylist); 1290 + klist_add_head(&b, &mylist); 1291 + 1292 + klist_add_behind(&c, &a); 1293 + KUNIT_EXPECT_EQ(test, node_count, 3); 1294 + KUNIT_EXPECT_PTR_EQ(test, last_node, &c); 1295 + 1296 + klist_add_behind(&d, &b); 1297 + KUNIT_EXPECT_EQ(test, node_count, 4); 1298 + KUNIT_EXPECT_PTR_EQ(test, last_node, &d); 1299 + 1300 + klist_iter_init(&mylist, &i); 1301 + 1302 + /* should be [list] -> b -> d -> a -> c*/ 1303 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b); 1304 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &d); 1305 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a); 1306 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &c); 1307 + KUNIT_EXPECT_NULL(test, klist_next(&i)); 1308 + 1309 + klist_iter_exit(&i); 1310 + 1311 + } 1312 + 1313 + static void klist_test_add_before(struct kunit *test) 1314 + { 1315 + struct klist_node a, b, c, d; 1316 + struct klist mylist; 1317 + struct klist_iter i; 1318 + 1319 + node_count = 0; 1320 + klist_init(&mylist, &check_node, NULL); 1321 + 1322 + klist_add_head(&a, &mylist); 1323 + klist_add_head(&b, &mylist); 1324 + klist_add_before(&c, &a); 1325 + KUNIT_EXPECT_EQ(test, node_count, 3); 1326 + KUNIT_EXPECT_PTR_EQ(test, last_node, &c); 1327 + 1328 + klist_add_before(&d, &b); 1329 + KUNIT_EXPECT_EQ(test, node_count, 4); 1330 + KUNIT_EXPECT_PTR_EQ(test, last_node, &d); 1331 + 1332 + klist_iter_init(&mylist, &i); 1333 + 1334 + /* should be [list] -> b -> d -> a -> c*/ 1335 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &d); 1336 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b); 1337 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &c); 1338 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a); 1339 + KUNIT_EXPECT_NULL(test, klist_next(&i)); 1340 + 1341 + klist_iter_exit(&i); 1342 + 1343 + } 1344 + 1345 + /* 1346 + * Verify that klist_del() delays the deletion of a node until there 1347 + * are no other references to it 1348 + */ 1349 + static void klist_test_del_refcount_greater_than_zero(struct kunit *test) 1350 + { 1351 + struct klist_node a, b, c, d; 1352 + struct klist mylist; 1353 + struct klist_iter i; 1354 + 1355 + node_count = 0; 1356 + klist_init(&mylist, &check_node, &check_delete_node); 1357 + 1358 + /* Add nodes a,b,c,d to the list*/ 1359 + klist_add_tail(&a, &mylist); 1360 + klist_add_tail(&b, &mylist); 1361 + klist_add_tail(&c, &mylist); 1362 + klist_add_tail(&d, &mylist); 1363 + 1364 + klist_iter_init(&mylist, &i); 1365 + 1366 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a); 1367 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b); 1368 + /* Advance the iterator to point to node c*/ 1369 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &c); 1370 + 1371 + /* Try to delete node c while there is a reference to it*/ 1372 + klist_del(&c); 1373 + 1374 + /* 1375 + * Verify that node c is still attached to the list even after being 1376 + * deleted. Since the iterator still points to c, the reference count is not 1377 + * decreased to 0 1378 + */ 1379 + KUNIT_EXPECT_TRUE(test, klist_node_attached(&c)); 1380 + 1381 + /* Check that node c has not been removed yet*/ 1382 + KUNIT_EXPECT_EQ(test, node_count, 4); 1383 + KUNIT_EXPECT_PTR_EQ(test, last_node, &d); 1384 + 1385 + klist_iter_exit(&i); 1386 + 1387 + /* 1388 + * Since the iterator is no longer pointing to node c, node c is removed 1389 + * from the list 1390 + */ 1391 + KUNIT_EXPECT_EQ(test, node_count, 3); 1392 + KUNIT_EXPECT_PTR_EQ(test, last_node, &c); 1393 + 1394 + } 1395 + 1396 + /* 1397 + * Verify that klist_del() deletes a node immediately when there are no 1398 + * other references to it. 1399 + */ 1400 + static void klist_test_del_refcount_zero(struct kunit *test) 1401 + { 1402 + struct klist_node a, b, c, d; 1403 + struct klist mylist; 1404 + struct klist_iter i; 1405 + 1406 + node_count = 0; 1407 + klist_init(&mylist, &check_node, &check_delete_node); 1408 + 1409 + /* Add nodes a,b,c,d to the list*/ 1410 + klist_add_tail(&a, &mylist); 1411 + klist_add_tail(&b, &mylist); 1412 + klist_add_tail(&c, &mylist); 1413 + klist_add_tail(&d, &mylist); 1414 + /* Delete node c*/ 1415 + klist_del(&c); 1416 + 1417 + /* Check that node c is deleted from the list*/ 1418 + KUNIT_EXPECT_EQ(test, node_count, 3); 1419 + KUNIT_EXPECT_PTR_EQ(test, last_node, &c); 1420 + 1421 + /* Should be [list] -> a -> b -> d*/ 1422 + klist_iter_init(&mylist, &i); 1423 + 1424 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a); 1425 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b); 1426 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &d); 1427 + KUNIT_EXPECT_NULL(test, klist_next(&i)); 1428 + 1429 + klist_iter_exit(&i); 1430 + 1431 + } 1432 + 1433 + static void klist_test_remove(struct kunit *test) 1434 + { 1435 + /* This test doesn't check correctness under concurrent access */ 1436 + struct klist_node a, b, c, d; 1437 + struct klist mylist; 1438 + struct klist_iter i; 1439 + 1440 + node_count = 0; 1441 + klist_init(&mylist, &check_node, &check_delete_node); 1442 + 1443 + /* Add nodes a,b,c,d to the list*/ 1444 + klist_add_tail(&a, &mylist); 1445 + klist_add_tail(&b, &mylist); 1446 + klist_add_tail(&c, &mylist); 1447 + klist_add_tail(&d, &mylist); 1448 + /* Delete node c*/ 1449 + klist_remove(&c); 1450 + 1451 + /* Check the nodes in the list*/ 1452 + KUNIT_EXPECT_EQ(test, node_count, 3); 1453 + KUNIT_EXPECT_PTR_EQ(test, last_node, &c); 1454 + 1455 + /* should be [list] -> a -> b -> d*/ 1456 + klist_iter_init(&mylist, &i); 1457 + 1458 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a); 1459 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b); 1460 + KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &d); 1461 + KUNIT_EXPECT_NULL(test, klist_next(&i)); 1462 + 1463 + klist_iter_exit(&i); 1464 + 1465 + } 1466 + 1467 + static void klist_test_node_attached(struct kunit *test) 1468 + { 1469 + struct klist_node a = {}; 1470 + struct klist mylist; 1471 + 1472 + klist_init(&mylist, NULL, NULL); 1473 + 1474 + KUNIT_EXPECT_FALSE(test, klist_node_attached(&a)); 1475 + klist_add_head(&a, &mylist); 1476 + KUNIT_EXPECT_TRUE(test, klist_node_attached(&a)); 1477 + klist_del(&a); 1478 + KUNIT_EXPECT_FALSE(test, klist_node_attached(&a)); 1479 + 1480 + } 1481 + 1482 + static struct kunit_case klist_test_cases[] = { 1483 + KUNIT_CASE(klist_test_add_tail), 1484 + KUNIT_CASE(klist_test_add_head), 1485 + KUNIT_CASE(klist_test_add_behind), 1486 + KUNIT_CASE(klist_test_add_before), 1487 + KUNIT_CASE(klist_test_del_refcount_greater_than_zero), 1488 + KUNIT_CASE(klist_test_del_refcount_zero), 1489 + KUNIT_CASE(klist_test_remove), 1490 + KUNIT_CASE(klist_test_node_attached), 1491 + {}, 1492 + }; 1493 + 1494 + static struct kunit_suite klist_test_module = { 1495 + .name = "klist", 1496 + .test_cases = klist_test_cases, 1497 + }; 1498 + 1499 + kunit_test_suites(&list_test_module, &hlist_test_module, &klist_test_module); 1204 1500 1205 1501 MODULE_LICENSE("GPL v2");