From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.6 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E5E0CA9EA0 for ; Fri, 18 Oct 2019 21:22:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E6E5C2089C for ; Fri, 18 Oct 2019 21:21:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1571433720; bh=YbTULRwISWfjjDD4znshcowXy/s5N/Hb8TjkXW9sFL0=; h=Subject:To:Cc:References:From:Date:In-Reply-To:List-ID:From; b=ufpl2TuGVv59wHFwm71Y0PgDjgs6DoQuo4WT1ZkO5Kgk/9g+kS39A5uSEdQwyFfSF HtYjNulYVXBi8W1RIqg/jpSOzk/GindmqUH8C+k9SdaKisC3JXxGmSaRCJvSU7ctcD fIStMp6+kYB7eouTPgQPG0jqNjOl+6otwK4FPqBs= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2436726AbfJRVV7 (ORCPT ); Fri, 18 Oct 2019 17:21:59 -0400 Received: from mail.kernel.org ([198.145.29.99]:56098 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2394432AbfJRVV7 (ORCPT ); Fri, 18 Oct 2019 17:21:59 -0400 Received: from [192.168.1.112] (c-24-9-64-241.hsd1.co.comcast.net [24.9.64.241]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 4745720679; Fri, 18 Oct 2019 21:21:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1571433717; bh=YbTULRwISWfjjDD4znshcowXy/s5N/Hb8TjkXW9sFL0=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=IIcOdx3s+VUR0O0AtqVtYbXlxyK47jydvRIvmqxKsTd7wjXBWc1qIVYcTECKNLdm4 9f6lmddnKJkBIzObs54ffWQPZLe8/86P3bFTzyWvWgZf3yLZHlzWZVl4+k9li+0Xwv 8mBb6SnCTZDGJad0i+O4XD8p3UFP6dhA0/D1TCSw= Subject: Re: [PATCH linux-kselftest/test v2] lib/list-test: add a test for the 'list' doubly linked list To: 20191007213633.92565-1-davidgow@google.com, brendanhiggins@google.com, akpm@linux-foundation.org, keescook@chromium.org Cc: linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, David Gow , shuah References: <20191010185631.26541-1-davidgow@google.com> From: shuah Message-ID: <800a71d2-fd55-f890-e9bb-410534f2d7c0@kernel.org> Date: Fri, 18 Oct 2019 15:21:34 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 MIME-Version: 1.0 In-Reply-To: <20191010185631.26541-1-davidgow@google.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Hi David, On 10/10/19 12:56 PM, David Gow wrote: > Add a KUnit test for the kernel doubly linked list implementation in > include/linux/list.h > > Each test case (list_test_x) is focused on testing the behaviour of the > list function/macro 'x'. None of the tests pass invalid lists to these > macros, and so should behave identically with DEBUG_LIST enabled and > disabled. > > Note that, at present, it only tests the list_ types (not the > singly-linked hlist_), and does not yet test all of the > list_for_each_entry* macros (and some related things like > list_prepare_entry). > > Signed-off-by: David Gow > --- > Addressed the various comments on v1. The biggest change is the renaming > of all of the testcases from the form x_test to list_test_x. I'm not > super happy with how that looks (not the least because it ends up with > 'list' twice), but it is more consistent with the proc/sysctl tests. > > I am sorry for commenting on this late. I have a comment on the config option naming. > MAINTAINERS | 5 + > lib/Kconfig.debug | 12 + > lib/Makefile | 3 + > lib/list-test.c | 738 ++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 758 insertions(+) > create mode 100644 lib/list-test.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 7ef985e01457..9ccabdb25a26 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -9504,6 +9504,11 @@ F: Documentation/misc-devices/lis3lv02d.rst > F: drivers/misc/lis3lv02d/ > F: drivers/platform/x86/hp_accel.c > > +LIST UNIT TEST > +M: David Gow > +S: Maintained > +F: lib/list-test.c > + > LIVE PATCHING > M: Josh Poimboeuf > M: Jiri Kosina > diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug > index a3017a5dadcd..7b648141ff52 100644 > --- a/lib/Kconfig.debug > +++ b/lib/Kconfig.debug > @@ -1961,6 +1961,18 @@ config SYSCTL_KUNIT_TEST > > If unsure, say N. > > +config LIST_TEST It is a good idea to have KUNIT in the naming and it is consistent with the ext4 test naming which is CONFIG_EXT4_KUNIT_TESTS > + bool "KUnit Test for Kernel Linked-list structures" > + depends on KUNIT > + help > + This builds the linked list unit test, which runs on boot. What happens if this fails - does the system boot. Please capture this information here as well as in the commit log. I also would like to wording similar to the what ext4 test - definitely the part about "not for inclusion into a production build." "KUnit tests run during boot and output the results to the debug log in TAP format (http://testanything.org/). Only useful for kernel devs running KUnit test harness and are not for inclusion into a production build." > + It tests that the API and basic functionality of the list_head type > + and associated macros. > + For more information on KUnit and unit tests in general please refer > + to the KUnit documentation in Documentation/dev-tools/kunit/. > + > + If unsure, say N. > + > config TEST_UDELAY > tristate "udelay test driver" > help > diff --git a/lib/Makefile b/lib/Makefile > index bba1fd5485f7..309e174ee35d 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -292,3 +292,6 @@ obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o > obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o > obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o > obj-$(CONFIG_OBJAGG) += objagg.o > + > +# KUnit tests > +obj-$(CONFIG_LIST_TEST) += list-test.o > diff --git a/lib/list-test.c b/lib/list-test.c > new file mode 100644 > index 000000000000..52522ba83a68 > --- /dev/null > +++ b/lib/list-test.c > @@ -0,0 +1,738 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * KUnit test for the Kernel Linked-list structures. > + * > + * Copyright (C) 2019, Google LLC. > + * Author: David Gow > + */ > +#include > + > +#include > + > +struct list_test_struct { > + int data; > + struct list_head list; > +}; > + > +static void list_test_list_init(struct kunit *test) > +{ > + /* Test the different ways of initialising a list. */ > + struct list_head list1 = LIST_HEAD_INIT(list1); > + struct list_head list2; > + LIST_HEAD(list3); > + struct list_head *list4; > + struct list_head *list5; > + > + INIT_LIST_HEAD(&list2); > + > + list4 = kzalloc(sizeof(*list4), 0); > + INIT_LIST_HEAD(list4); > + > + list5 = kmalloc(sizeof(*list5), 0); > + memset(list5, 0xFF, sizeof(*list5)); > + INIT_LIST_HEAD(list5); > + > + /* list_empty_careful() checks both next and prev. */ > + KUNIT_EXPECT_TRUE(test, list_empty_careful(&list1)); > + KUNIT_EXPECT_TRUE(test, list_empty_careful(&list2)); > + KUNIT_EXPECT_TRUE(test, list_empty_careful(&list3)); > + KUNIT_EXPECT_TRUE(test, list_empty_careful(list4)); > + KUNIT_EXPECT_TRUE(test, list_empty_careful(list5)); > + > + kfree(list4); > + kfree(list5); > +} > + > +static void list_test_list_add(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list); > + > + list_add(&a, &list); > + list_add(&b, &list); > + > + /* should be [list] -> b -> a */ > + KUNIT_EXPECT_PTR_EQ(test, list.next, &b); > + KUNIT_EXPECT_PTR_EQ(test, b.prev, &list); > + KUNIT_EXPECT_PTR_EQ(test, b.next, &a); > +} > + > +static void list_test_list_add_tail(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list); > + > + list_add_tail(&a, &list); > + list_add_tail(&b, &list); > + > + /* should be [list] -> a -> b */ > + KUNIT_EXPECT_PTR_EQ(test, list.next, &a); > + KUNIT_EXPECT_PTR_EQ(test, a.prev, &list); > + KUNIT_EXPECT_PTR_EQ(test, a.next, &b); > +} > + > +static void list_test_list_del(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list); > + > + list_add_tail(&a, &list); > + list_add_tail(&b, &list); > + > + /* before: [list] -> a -> b */ > + list_del(&a); > + > + /* now: [list] -> b */ > + KUNIT_EXPECT_PTR_EQ(test, list.next, &b); > + KUNIT_EXPECT_PTR_EQ(test, b.prev, &list); > +} > + > +static void list_test_list_replace(struct kunit *test) > +{ > + struct list_head a_old, a_new, b; > + LIST_HEAD(list); > + > + list_add_tail(&a_old, &list); > + list_add_tail(&b, &list); > + > + /* before: [list] -> a_old -> b */ > + list_replace(&a_old, &a_new); > + > + /* now: [list] -> a_new -> b */ > + KUNIT_EXPECT_PTR_EQ(test, list.next, &a_new); > + KUNIT_EXPECT_PTR_EQ(test, b.prev, &a_new); > +} > + > +static void list_test_list_replace_init(struct kunit *test) > +{ > + struct list_head a_old, a_new, b; > + LIST_HEAD(list); > + > + list_add_tail(&a_old, &list); > + list_add_tail(&b, &list); > + > + /* before: [list] -> a_old -> b */ > + list_replace_init(&a_old, &a_new); > + > + /* now: [list] -> a_new -> b */ > + KUNIT_EXPECT_PTR_EQ(test, list.next, &a_new); > + KUNIT_EXPECT_PTR_EQ(test, b.prev, &a_new); > + > + /* check a_old is empty (initialized) */ > + KUNIT_EXPECT_TRUE(test, list_empty_careful(&a_old)); > +} > + > +static void list_test_list_swap(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list); > + > + list_add_tail(&a, &list); > + list_add_tail(&b, &list); > + > + /* before: [list] -> a -> b */ > + list_swap(&a, &b); > + > + /* after: [list] -> b -> a */ > + KUNIT_EXPECT_PTR_EQ(test, &b, list.next); > + KUNIT_EXPECT_PTR_EQ(test, &a, list.prev); > + > + KUNIT_EXPECT_PTR_EQ(test, &a, b.next); > + KUNIT_EXPECT_PTR_EQ(test, &list, b.prev); > + > + KUNIT_EXPECT_PTR_EQ(test, &list, a.next); > + KUNIT_EXPECT_PTR_EQ(test, &b, a.prev); > +} > + > +static void list_test_list_del_init(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list); > + > + list_add_tail(&a, &list); > + list_add_tail(&b, &list); > + > + /* before: [list] -> a -> b */ > + list_del_init(&a); > + /* after: [list] -> b, a initialised */ > + > + KUNIT_EXPECT_PTR_EQ(test, list.next, &b); > + KUNIT_EXPECT_PTR_EQ(test, b.prev, &list); > + KUNIT_EXPECT_TRUE(test, list_empty_careful(&a)); > +} > + > +static void list_test_list_move(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + > + list_add_tail(&a, &list1); > + list_add_tail(&b, &list2); > + > + /* before: [list1] -> a, [list2] -> b */ > + list_move(&a, &list2); > + /* after: [list1] empty, [list2] -> a -> b */ > + > + KUNIT_EXPECT_TRUE(test, list_empty(&list1)); > + > + KUNIT_EXPECT_PTR_EQ(test, &a, list2.next); > + KUNIT_EXPECT_PTR_EQ(test, &b, a.next); > +} > + > +static void list_test_list_move_tail(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + > + list_add_tail(&a, &list1); > + list_add_tail(&b, &list2); > + > + /* before: [list1] -> a, [list2] -> b */ > + list_move_tail(&a, &list2); > + /* after: [list1] empty, [list2] -> b -> a */ > + > + KUNIT_EXPECT_TRUE(test, list_empty(&list1)); > + > + KUNIT_EXPECT_PTR_EQ(test, &b, list2.next); > + KUNIT_EXPECT_PTR_EQ(test, &a, b.next); > +} > + > +static void list_test_list_bulk_move_tail(struct kunit *test) > +{ > + struct list_head a, b, c, d, x, y; > + struct list_head *list1_values[] = { &x, &b, &c, &y }; > + struct list_head *list2_values[] = { &a, &d }; > + struct list_head *ptr; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + int i = 0; > + > + list_add_tail(&x, &list1); > + list_add_tail(&y, &list1); > + > + list_add_tail(&a, &list2); > + list_add_tail(&b, &list2); > + list_add_tail(&c, &list2); > + list_add_tail(&d, &list2); > + > + /* before: [list1] -> x -> y, [list2] -> a -> b -> c -> d */ > + list_bulk_move_tail(&y, &b, &c); > + /* after: [list1] -> x -> b -> c -> y, [list2] -> a -> d */ > + > + list_for_each(ptr, &list1) { > + KUNIT_EXPECT_PTR_EQ(test, ptr, list1_values[i]); > + i++; > + } > + KUNIT_EXPECT_EQ(test, i, 4); > + i = 0; > + list_for_each(ptr, &list2) { > + KUNIT_EXPECT_PTR_EQ(test, ptr, list2_values[i]); > + i++; > + } > + KUNIT_EXPECT_EQ(test, i, 2); > +} > + > +static void list_test_list_is_first(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list); > + > + list_add_tail(&a, &list); > + list_add_tail(&b, &list); > + > + KUNIT_EXPECT_TRUE(test, list_is_first(&a, &list)); > + KUNIT_EXPECT_FALSE(test, list_is_first(&b, &list)); > +} > + > +static void list_test_list_is_last(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list); > + > + list_add_tail(&a, &list); > + list_add_tail(&b, &list); > + > + KUNIT_EXPECT_FALSE(test, list_is_last(&a, &list)); > + KUNIT_EXPECT_TRUE(test, list_is_last(&b, &list)); > +} > + > +static void list_test_list_empty(struct kunit *test) > +{ > + struct list_head a; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + > + list_add_tail(&a, &list1); > + > + KUNIT_EXPECT_FALSE(test, list_empty(&list1)); > + KUNIT_EXPECT_TRUE(test, list_empty(&list2)); > +} > + > +static void list_test_list_empty_careful(struct kunit *test) > +{ > + /* This test doesn't check correctness under concurrent access */ > + struct list_head a; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + > + list_add_tail(&a, &list1); > + > + KUNIT_EXPECT_FALSE(test, list_empty_careful(&list1)); > + KUNIT_EXPECT_TRUE(test, list_empty_careful(&list2)); > +} > + > +static void list_test_list_rotate_left(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list); > + > + list_add_tail(&a, &list); > + list_add_tail(&b, &list); > + > + /* before: [list] -> a -> b */ > + list_rotate_left(&list); > + /* after: [list] -> b -> a */ > + > + KUNIT_EXPECT_PTR_EQ(test, list.next, &b); > + KUNIT_EXPECT_PTR_EQ(test, b.prev, &list); > + KUNIT_EXPECT_PTR_EQ(test, b.next, &a); > +} > + > +static void list_test_list_rotate_to_front(struct kunit *test) > +{ > + struct list_head a, b, c, d; > + struct list_head *list_values[] = { &c, &d, &a, &b }; > + struct list_head *ptr; > + LIST_HEAD(list); > + int i = 0; > + > + list_add_tail(&a, &list); > + list_add_tail(&b, &list); > + list_add_tail(&c, &list); > + list_add_tail(&d, &list); > + > + /* before: [list] -> a -> b -> c -> d */ > + list_rotate_to_front(&c, &list); > + /* after: [list] -> c -> d -> a -> b */ > + > + list_for_each(ptr, &list) { > + KUNIT_EXPECT_PTR_EQ(test, ptr, list_values[i]); > + i++; > + } > + KUNIT_EXPECT_EQ(test, i, 4); > +} > + > +static void list_test_list_is_singular(struct kunit *test) > +{ > + struct list_head a, b; > + LIST_HEAD(list); > + > + /* [list] empty */ > + KUNIT_EXPECT_FALSE(test, list_is_singular(&list)); > + > + list_add_tail(&a, &list); > + > + /* [list] -> a */ > + KUNIT_EXPECT_TRUE(test, list_is_singular(&list)); > + > + list_add_tail(&b, &list); > + > + /* [list] -> a -> b */ > + KUNIT_EXPECT_FALSE(test, list_is_singular(&list)); > +} > + > +static void list_test_list_cut_position(struct kunit *test) > +{ > + struct list_head entries[3], *cur; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + int i = 0; > + > + list_add_tail(&entries[0], &list1); > + list_add_tail(&entries[1], &list1); > + list_add_tail(&entries[2], &list1); > + > + /* before: [list1] -> entries[0] -> entries[1] -> entries[2] */ > + list_cut_position(&list2, &list1, &entries[1]); > + /* after: [list2] -> entries[0] -> entries[1], [list1] -> entries[2] */ > + > + list_for_each(cur, &list2) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i++; > + } > + > + KUNIT_EXPECT_EQ(test, i, 2); > + > + list_for_each(cur, &list1) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i++; > + } > +} > + > +static void list_test_list_cut_before(struct kunit *test) > +{ > + struct list_head entries[3], *cur; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + int i = 0; > + > + list_add_tail(&entries[0], &list1); > + list_add_tail(&entries[1], &list1); > + list_add_tail(&entries[2], &list1); > + > + /* before: [list1] -> entries[0] -> entries[1] -> entries[2] */ > + list_cut_before(&list2, &list1, &entries[1]); > + /* after: [list2] -> entries[0], [list1] -> entries[1] -> entries[2] */ > + > + list_for_each(cur, &list2) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i++; > + } > + > + KUNIT_EXPECT_EQ(test, i, 1); > + > + list_for_each(cur, &list1) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i++; > + } > +} > + > +static void list_test_list_splice(struct kunit *test) > +{ > + struct list_head entries[5], *cur; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + int i = 0; > + > + list_add_tail(&entries[0], &list1); > + list_add_tail(&entries[1], &list1); > + list_add_tail(&entries[2], &list2); > + list_add_tail(&entries[3], &list2); > + list_add_tail(&entries[4], &list1); > + > + /* before: [list1]->e[0]->e[1]->e[4], [list2]->e[2]->e[3] */ > + list_splice(&list2, &entries[1]); > + /* after: [list1]->e[0]->e[1]->e[2]->e[3]->e[4], [list2] uninit */ > + > + list_for_each(cur, &list1) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i++; > + } > + > + KUNIT_EXPECT_EQ(test, i, 5); > +} > + > +static void list_test_list_splice_tail(struct kunit *test) > +{ > + struct list_head entries[5], *cur; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + int i = 0; > + > + list_add_tail(&entries[0], &list1); > + list_add_tail(&entries[1], &list1); > + list_add_tail(&entries[2], &list2); > + list_add_tail(&entries[3], &list2); > + list_add_tail(&entries[4], &list1); > + > + /* before: [list1]->e[0]->e[1]->e[4], [list2]->e[2]->e[3] */ > + list_splice_tail(&list2, &entries[4]); > + /* after: [list1]->e[0]->e[1]->e[2]->e[3]->e[4], [list2] uninit */ > + > + list_for_each(cur, &list1) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i++; > + } > + > + KUNIT_EXPECT_EQ(test, i, 5); > +} > + > +static void list_test_list_splice_init(struct kunit *test) > +{ > + struct list_head entries[5], *cur; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + int i = 0; > + > + list_add_tail(&entries[0], &list1); > + list_add_tail(&entries[1], &list1); > + list_add_tail(&entries[2], &list2); > + list_add_tail(&entries[3], &list2); > + list_add_tail(&entries[4], &list1); > + > + /* before: [list1]->e[0]->e[1]->e[4], [list2]->e[2]->e[3] */ > + list_splice_init(&list2, &entries[1]); > + /* after: [list1]->e[0]->e[1]->e[2]->e[3]->e[4], [list2] empty */ > + > + list_for_each(cur, &list1) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i++; > + } > + > + KUNIT_EXPECT_EQ(test, i, 5); > + > + KUNIT_EXPECT_TRUE(test, list_empty_careful(&list2)); > +} > + > +static void list_test_list_splice_tail_init(struct kunit *test) > +{ > + struct list_head entries[5], *cur; > + LIST_HEAD(list1); > + LIST_HEAD(list2); > + int i = 0; > + > + list_add_tail(&entries[0], &list1); > + list_add_tail(&entries[1], &list1); > + list_add_tail(&entries[2], &list2); > + list_add_tail(&entries[3], &list2); > + list_add_tail(&entries[4], &list1); > + > + /* before: [list1]->e[0]->e[1]->e[4], [list2]->e[2]->e[3] */ > + list_splice_tail_init(&list2, &entries[4]); > + /* after: [list1]->e[0]->e[1]->e[2]->e[3]->e[4], [list2] empty */ > + > + list_for_each(cur, &list1) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i++; > + } > + > + KUNIT_EXPECT_EQ(test, i, 5); > + > + KUNIT_EXPECT_TRUE(test, list_empty_careful(&list2)); > +} > + > +static void list_test_list_entry(struct kunit *test) > +{ > + struct list_test_struct test_struct; > + > + KUNIT_EXPECT_PTR_EQ(test, &test_struct, list_entry(&(test_struct.list), struct list_test_struct, list)); > +} > + > +static void list_test_list_first_entry(struct kunit *test) > +{ > + struct list_test_struct test_struct1, test_struct2; > + LIST_HEAD(list); > + > + list_add_tail(&test_struct1.list, &list); > + list_add_tail(&test_struct2.list, &list); > + > + > + KUNIT_EXPECT_PTR_EQ(test, &test_struct1, list_first_entry(&list, struct list_test_struct, list)); > +} > + > +static void list_test_list_last_entry(struct kunit *test) > +{ > + struct list_test_struct test_struct1, test_struct2; > + LIST_HEAD(list); > + > + list_add_tail(&test_struct1.list, &list); > + list_add_tail(&test_struct2.list, &list); > + > + > + KUNIT_EXPECT_PTR_EQ(test, &test_struct2, list_last_entry(&list, struct list_test_struct, list)); > +} > + > +static void list_test_list_first_entry_or_null(struct kunit *test) > +{ > + struct list_test_struct test_struct1, test_struct2; > + LIST_HEAD(list); > + > + KUNIT_EXPECT_FALSE(test, list_first_entry_or_null(&list, struct list_test_struct, list)); > + > + list_add_tail(&test_struct1.list, &list); > + list_add_tail(&test_struct2.list, &list); > + > + KUNIT_EXPECT_PTR_EQ(test, &test_struct1, list_first_entry_or_null(&list, struct list_test_struct, list)); > +} > + > +static void list_test_list_next_entry(struct kunit *test) > +{ > + struct list_test_struct test_struct1, test_struct2; > + LIST_HEAD(list); > + > + list_add_tail(&test_struct1.list, &list); > + list_add_tail(&test_struct2.list, &list); > + > + > + KUNIT_EXPECT_PTR_EQ(test, &test_struct2, list_next_entry(&test_struct1, list)); > +} > + > +static void list_test_list_prev_entry(struct kunit *test) > +{ > + struct list_test_struct test_struct1, test_struct2; > + LIST_HEAD(list); > + > + list_add_tail(&test_struct1.list, &list); > + list_add_tail(&test_struct2.list, &list); > + > + > + KUNIT_EXPECT_PTR_EQ(test, &test_struct1, list_prev_entry(&test_struct2, list)); > +} > + > +static void list_test_list_for_each(struct kunit *test) > +{ > + struct list_head entries[3], *cur; > + LIST_HEAD(list); > + int i = 0; > + > + list_add_tail(&entries[0], &list); > + list_add_tail(&entries[1], &list); > + list_add_tail(&entries[2], &list); > + > + list_for_each(cur, &list) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i++; > + } > + > + KUNIT_EXPECT_EQ(test, i, 3); > +} > + > +static void list_test_list_for_each_prev(struct kunit *test) > +{ > + struct list_head entries[3], *cur; > + LIST_HEAD(list); > + int i = 2; > + > + list_add_tail(&entries[0], &list); > + list_add_tail(&entries[1], &list); > + list_add_tail(&entries[2], &list); > + > + list_for_each_prev(cur, &list) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + i--; > + } > + > + KUNIT_EXPECT_EQ(test, i, -1); > +} > + > +static void list_test_list_for_each_safe(struct kunit *test) > +{ > + struct list_head entries[3], *cur, *n; > + LIST_HEAD(list); > + int i = 0; > + > + > + list_add_tail(&entries[0], &list); > + list_add_tail(&entries[1], &list); > + list_add_tail(&entries[2], &list); > + > + list_for_each_safe(cur, n, &list) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + list_del(&entries[i]); > + i++; > + } > + > + KUNIT_EXPECT_EQ(test, i, 3); > + KUNIT_EXPECT_TRUE(test, list_empty(&list)); > +} > + > +static void list_test_list_for_each_prev_safe(struct kunit *test) > +{ > + struct list_head entries[3], *cur, *n; > + LIST_HEAD(list); > + int i = 2; > + > + list_add_tail(&entries[0], &list); > + list_add_tail(&entries[1], &list); > + list_add_tail(&entries[2], &list); > + > + list_for_each_prev_safe(cur, n, &list) { > + KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); > + list_del(&entries[i]); > + i--; > + } > + > + KUNIT_EXPECT_EQ(test, i, -1); > + KUNIT_EXPECT_TRUE(test, list_empty(&list)); > +} > + > +static void list_test_list_for_each_entry(struct kunit *test) > +{ > + struct list_test_struct entries[5], *cur; > + static LIST_HEAD(list); > + int i = 0; > + > + for (i = 0; i < 5; ++i) { > + entries[i].data = i; > + list_add_tail(&entries[i].list, &list); > + } > + > + i = 0; > + > + list_for_each_entry(cur, &list, list) { > + KUNIT_EXPECT_EQ(test, cur->data, i); > + i++; > + } > + > + KUNIT_EXPECT_EQ(test, i, 5); > +} > + > +static void list_test_list_for_each_entry_reverse(struct kunit *test) > +{ > + struct list_test_struct entries[5], *cur; > + static LIST_HEAD(list); > + int i = 0; > + > + for (i = 0; i < 5; ++i) { > + entries[i].data = i; > + list_add_tail(&entries[i].list, &list); > + } > + > + i = 4; > + > + list_for_each_entry_reverse(cur, &list, list) { > + KUNIT_EXPECT_EQ(test, cur->data, i); > + i--; > + } > + > + KUNIT_EXPECT_EQ(test, i, -1); > +} > + > +static struct kunit_case list_test_cases[] = { > + KUNIT_CASE(list_test_list_init), > + KUNIT_CASE(list_test_list_add), > + KUNIT_CASE(list_test_list_add_tail), > + KUNIT_CASE(list_test_list_del), > + KUNIT_CASE(list_test_list_replace), > + KUNIT_CASE(list_test_list_replace_init), > + KUNIT_CASE(list_test_list_swap), > + KUNIT_CASE(list_test_list_del_init), > + KUNIT_CASE(list_test_list_move), > + KUNIT_CASE(list_test_list_move_tail), > + KUNIT_CASE(list_test_list_bulk_move_tail), > + KUNIT_CASE(list_test_list_is_first), > + KUNIT_CASE(list_test_list_is_last), > + KUNIT_CASE(list_test_list_empty), > + KUNIT_CASE(list_test_list_empty_careful), > + KUNIT_CASE(list_test_list_rotate_left), > + KUNIT_CASE(list_test_list_rotate_to_front), > + KUNIT_CASE(list_test_list_is_singular), > + KUNIT_CASE(list_test_list_cut_position), > + KUNIT_CASE(list_test_list_cut_before), > + KUNIT_CASE(list_test_list_splice), > + KUNIT_CASE(list_test_list_splice_tail), > + KUNIT_CASE(list_test_list_splice_init), > + KUNIT_CASE(list_test_list_splice_tail_init), > + KUNIT_CASE(list_test_list_entry), > + KUNIT_CASE(list_test_list_first_entry), > + KUNIT_CASE(list_test_list_last_entry), > + KUNIT_CASE(list_test_list_first_entry_or_null), > + KUNIT_CASE(list_test_list_next_entry), > + KUNIT_CASE(list_test_list_prev_entry), > + KUNIT_CASE(list_test_list_for_each), > + KUNIT_CASE(list_test_list_for_each_prev), > + KUNIT_CASE(list_test_list_for_each_safe), > + KUNIT_CASE(list_test_list_for_each_prev_safe), > + KUNIT_CASE(list_test_list_for_each_entry), > + KUNIT_CASE(list_test_list_for_each_entry_reverse), > + {}, > +}; > + > +static struct kunit_suite list_test_module = { > + .name = "list-test", Please use kunit in the name here. > + .test_cases = list_test_cases, > +}; > + > +kunit_test_suite(list_test_module); > thanks, -- Shuah