Received: by 2002:ac0:bc90:0:0:0:0:0 with SMTP id a16csp215376img; Thu, 21 Mar 2019 18:16:16 -0700 (PDT) X-Google-Smtp-Source: APXvYqyFdypW3v5nPUJmVR/8CHb8OrPb7SJpY/Ql2VL5bNp+Pqqz7bwogUb45ItCDUXfoeJ2wt8f X-Received: by 2002:a65:52c9:: with SMTP id z9mr6142440pgp.227.1553217376598; Thu, 21 Mar 2019 18:16:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1553217376; cv=none; d=google.com; s=arc-20160816; b=zO+50TO1VQPDJ3j/niFNkNhRQkkUecOXUS1gAay6UBk8WO9nUDOmd6z/v/ug7cIYRg ttADQsidiR9BytMJp4hXb1LkwM0YJRaGFjxiPd4iR10G1NdN3vFgcKApH77xQ1/BL5PF i8Rti8FPNDLvXSZkFx92LinENt4O/q0yJ6tbBLJu6QpCm0vbQVpriIR7Fz3yVAlrqxBR oJnlT23TL7+xOore4HBDQvCITVRyqu5D1x5rMyKh/MyLD9X6wM1XYVtc33SiJCFW7eAZ tMU8IRLg7sqGevroqrdTr71jVeeZ9cvveH+LEd5Q/wUJwNVN3JFOH1XJsQnE0EyKpTVB bd+g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:dkim-signature; bh=V90qdfFQGBsn+mK4fjUdRUzkVQpl7RD5gYUSfaew7rM=; b=K57P+bpA0JzjnBaGWRSDUp+3YPMVzCLR4sNSUpr3PF3vLHUelygXLFeWqN/B0QtXVQ mLdts+DnTRawMyrxQrLsSzpVPKsS99l8glTRZefwNAiLc9bOXhCtyvPpa2UBP/O7o43V 7cLUK33zmqhC9aA8NBLNa8B3WRX/chakE/zWUZHFV3ounuSoAdsY0FH9doANOW933dR7 d0R+CjBNQ8JGIiYLuUcKIKV3KQVMBMjmQWIMH7HVMjW+0DGyjXNLfa0Q34sPr79YN94b SaBNM6Nkw6fBOL1dqhm/yivBrK1k8x9BOgfshMrGkPSOsxGMJNxB4Wfci78GAVFSU90K rLLg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=mz+EsFBQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f5si5466023pgo.394.2019.03.21.18.15.58; Thu, 21 Mar 2019 18:16:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=mz+EsFBQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727487AbfCVBPE (ORCPT + 99 others); Thu, 21 Mar 2019 21:15:04 -0400 Received: from mail-pg1-f195.google.com ([209.85.215.195]:46776 "EHLO mail-pg1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725999AbfCVBPE (ORCPT ); Thu, 21 Mar 2019 21:15:04 -0400 Received: by mail-pg1-f195.google.com with SMTP id a22so259717pgg.13; Thu, 21 Mar 2019 18:15:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=V90qdfFQGBsn+mK4fjUdRUzkVQpl7RD5gYUSfaew7rM=; b=mz+EsFBQMPLp8xIgsQn7i1PtrHko+w1XRfc0XVVpJPpGcqS1hGVW7rypRJc8jw0VBC krtfxKrullXSzI5xAqmKJ64wrIetvhR/cZ3c4nupw9PJywqulN8PK5PqFhX5Yt5A77HK y3b4Ox2b+DQHftQOASwx4PSAw0oQbXs1GBahIJMFPk2kqdKH1jEPPkXUozA+Mpki6be/ dRCnCS5EK2GZ53t292BESqz4GS5yBaImteBz139lqOnOYKx01ifcXeax5KDHK2o/HD7l XCMGEXSSRhdcts3nwwWQEvIXh3O2dz03JWbUq7/VIsUWVoPRid4jNkPUJNhV0SM9Ie9G ZBCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=V90qdfFQGBsn+mK4fjUdRUzkVQpl7RD5gYUSfaew7rM=; b=cyMqX+ZY0yrZFhtwEtk0m49FLsSAIf7/Bklxtbe2bAt44nmtl6oH7/HkWPKVM+9+Nu dLBJB+287u6K3Iqt6m3D8JcyCQPsbP1KYXzQXLt6NgUfpEh30eSBu6qKC650yjwwqE6I 8B/8Sz4pL7WSr1XUxeKhqnSk/hO1WBdRNpkxnnSekmikix0Ne2DshSErY+hS74bOQ+h/ Z+Q35UA8uWIYmBqHVzpK5bhpH3p1eVnin9HzoLHBkYPAydMIduW009JJZXWzPFfvOheO 9VHoC5liEmk2NheBfQwGai3MviQg2vsy43sW92JqwQtINz5L3TvDIDc72RJ99+fMDyNj pJ3A== X-Gm-Message-State: APjAAAUfe5S0k9eF7jeCBEvD8BTTnmzrhcTwLte+VxUps31/LMKU8NUn JTc8fyLt8JJ74af4uR98Qoo= X-Received: by 2002:a17:902:a40d:: with SMTP id p13mr6574231plq.144.1553217302046; Thu, 21 Mar 2019 18:15:02 -0700 (PDT) Received: from [192.168.1.70] (c-24-6-192-50.hsd1.ca.comcast.net. [24.6.192.50]) by smtp.gmail.com with ESMTPSA id f4sm7275164pgq.94.2019.03.21.18.14.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 21 Mar 2019 18:15:01 -0700 (PDT) Subject: Re: [RFC v4 16/17] of: unittest: split out a couple of test cases from unittest To: Brendan Higgins , keescook@google.com, mcgrof@kernel.org, shuah@kernel.org, robh@kernel.org, kieran.bingham@ideasonboard.com Cc: gregkh@linuxfoundation.org, joel@jms.id.au, mpe@ellerman.id.au, joe@perches.com, brakmo@fb.com, rostedt@goodmis.org, Tim.Bird@sony.com, khilman@baylibre.com, julia.lawall@lip6.fr, linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, jdike@addtoit.com, richard@nod.at, linux-um@lists.infradead.org, daniel@ffwll.ch, dri-devel@lists.freedesktop.org, dan.j.williams@intel.com, linux-nvdimm@lists.01.org, knut.omang@oracle.com, devicetree@vger.kernel.org, pmladek@suse.com, Alexander.Levin@microsoft.com, amir73il@gmail.com, dan.carpenter@oracle.com, wfg@linux.intel.com References: <20190214213729.21702-1-brendanhiggins@google.com> <20190214213729.21702-17-brendanhiggins@google.com> From: Frank Rowand Message-ID: Date: Thu, 21 Mar 2019 18:14:58 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.5.1 MIME-Version: 1.0 In-Reply-To: <20190214213729.21702-17-brendanhiggins@google.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2/14/19 1:37 PM, Brendan Higgins wrote: > Split out a couple of test cases that these features in base.c from the > unittest.c monolith. The intention is that we will eventually split out > all test cases and group them together based on what portion of device > tree they test. I still object to this patch. I do not want this code scattered into additional files. -Frank > > Signed-off-by: Brendan Higgins > --- > drivers/of/Makefile | 2 +- > drivers/of/base-test.c | 214 ++++++++++++++++++++++++ > drivers/of/test-common.c | 175 ++++++++++++++++++++ > drivers/of/test-common.h | 16 ++ > drivers/of/unittest.c | 345 +-------------------------------------- > 5 files changed, 407 insertions(+), 345 deletions(-) > create mode 100644 drivers/of/base-test.c > create mode 100644 drivers/of/test-common.c > create mode 100644 drivers/of/test-common.h > > diff --git a/drivers/of/Makefile b/drivers/of/Makefile > index 663a4af0cccd5..4a4bd527d586c 100644 > --- a/drivers/of/Makefile > +++ b/drivers/of/Makefile > @@ -8,7 +8,7 @@ obj-$(CONFIG_OF_PROMTREE) += pdt.o > obj-$(CONFIG_OF_ADDRESS) += address.o > obj-$(CONFIG_OF_IRQ) += irq.o > obj-$(CONFIG_OF_NET) += of_net.o > -obj-$(CONFIG_OF_UNITTEST) += unittest.o > +obj-$(CONFIG_OF_UNITTEST) += unittest.o base-test.o test-common.o > obj-$(CONFIG_OF_MDIO) += of_mdio.o > obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o > obj-$(CONFIG_OF_RESOLVE) += resolver.o > diff --git a/drivers/of/base-test.c b/drivers/of/base-test.c > new file mode 100644 > index 0000000000000..3d3f4f1b74800 > --- /dev/null > +++ b/drivers/of/base-test.c > @@ -0,0 +1,214 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Unit tests for functions defined in base.c. > + */ > +#include > + > +#include > + > +#include "test-common.h" > + > +static void of_unittest_find_node_by_name(struct kunit *test) > +{ > + struct device_node *np; > + const char *options, *name; > + > + np = of_find_node_by_path("/testcase-data"); > + name = kasprintf(GFP_KERNEL, "%pOF", np); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + KUNIT_EXPECT_STREQ_MSG(test, "/testcase-data", name, > + "find /testcase-data failed\n"); > + of_node_put(np); > + kfree(name); > + > + /* Test if trailing '/' works */ > + KUNIT_EXPECT_EQ_MSG(test, of_find_node_by_path("/testcase-data/"), NULL, > + "trailing '/' on /testcase-data/ should fail\n"); > + > + np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + name = kasprintf(GFP_KERNEL, "%pOF", np); > + KUNIT_EXPECT_STREQ_MSG( > + test, "/testcase-data/phandle-tests/consumer-a", name, > + "find /testcase-data/phandle-tests/consumer-a failed\n"); > + of_node_put(np); > + kfree(name); > + > + np = of_find_node_by_path("testcase-alias"); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + name = kasprintf(GFP_KERNEL, "%pOF", np); > + KUNIT_EXPECT_STREQ_MSG(test, "/testcase-data", name, > + "find testcase-alias failed\n"); > + of_node_put(np); > + kfree(name); > + > + /* Test if trailing '/' works on aliases */ > + KUNIT_EXPECT_EQ_MSG(test, of_find_node_by_path("testcase-alias/"), NULL, > + "trailing '/' on testcase-alias/ should fail\n"); > + > + np = of_find_node_by_path("testcase-alias/phandle-tests/consumer-a"); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + name = kasprintf(GFP_KERNEL, "%pOF", np); > + KUNIT_EXPECT_STREQ_MSG( > + test, "/testcase-data/phandle-tests/consumer-a", name, > + "find testcase-alias/phandle-tests/consumer-a failed\n"); > + of_node_put(np); > + kfree(name); > + > + KUNIT_EXPECT_EQ_MSG( > + test, > + np = of_find_node_by_path("/testcase-data/missing-path"), NULL, > + "non-existent path returned node %pOF\n", np); > + of_node_put(np); > + > + KUNIT_EXPECT_EQ_MSG( > + test, np = of_find_node_by_path("missing-alias"), NULL, > + "non-existent alias returned node %pOF\n", np); > + of_node_put(np); > + > + KUNIT_EXPECT_EQ_MSG( > + test, > + np = of_find_node_by_path("testcase-alias/missing-path"), NULL, > + "non-existent alias with relative path returned node %pOF\n", > + np); > + of_node_put(np); > + > + np = of_find_node_opts_by_path("/testcase-data:testoption", &options); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + KUNIT_EXPECT_STREQ_MSG(test, "testoption", options, > + "option path test failed\n"); > + of_node_put(np); > + > + np = of_find_node_opts_by_path("/testcase-data:test/option", &options); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + KUNIT_EXPECT_STREQ_MSG(test, "test/option", options, > + "option path test, subcase #1 failed\n"); > + of_node_put(np); > + > + np = of_find_node_opts_by_path("/testcase-data/testcase-device1:test/option", &options); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + KUNIT_EXPECT_STREQ_MSG(test, "test/option", options, > + "option path test, subcase #2 failed\n"); > + of_node_put(np); > + > + np = of_find_node_opts_by_path("/testcase-data:testoption", NULL); > + KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, np, > + "NULL option path test failed\n"); > + of_node_put(np); > + > + np = of_find_node_opts_by_path("testcase-alias:testaliasoption", > + &options); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + KUNIT_EXPECT_STREQ_MSG(test, "testaliasoption", options, > + "option alias path test failed\n"); > + of_node_put(np); > + > + np = of_find_node_opts_by_path("testcase-alias:test/alias/option", > + &options); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + KUNIT_EXPECT_STREQ_MSG(test, "test/alias/option", options, > + "option alias path test, subcase #1 failed\n"); > + of_node_put(np); > + > + np = of_find_node_opts_by_path("testcase-alias:testaliasoption", NULL); > + KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG( > + test, np, "NULL option alias path test failed\n"); > + of_node_put(np); > + > + options = "testoption"; > + np = of_find_node_opts_by_path("testcase-alias", &options); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + KUNIT_EXPECT_EQ_MSG(test, options, NULL, > + "option clearing test failed\n"); > + of_node_put(np); > + > + options = "testoption"; > + np = of_find_node_opts_by_path("/", &options); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + KUNIT_EXPECT_EQ_MSG(test, options, NULL, > + "option clearing root node test failed\n"); > + of_node_put(np); > +} > + > +static void of_unittest_dynamic(struct kunit *test) > +{ > + struct device_node *np; > + struct property *prop; > + > + np = of_find_node_by_path("/testcase-data"); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > + > + /* Array of 4 properties for the purpose of testing */ > + prop = kcalloc(4, sizeof(*prop), GFP_KERNEL); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, prop); > + > + /* Add a new property - should pass*/ > + prop->name = "new-property"; > + prop->value = "new-property-data"; > + prop->length = strlen(prop->value) + 1; > + KUNIT_EXPECT_EQ_MSG(test, of_add_property(np, prop), 0, > + "Adding a new property failed\n"); > + > + /* Try to add an existing property - should fail */ > + prop++; > + prop->name = "new-property"; > + prop->value = "new-property-data-should-fail"; > + prop->length = strlen(prop->value) + 1; > + KUNIT_EXPECT_NE_MSG(test, of_add_property(np, prop), 0, > + "Adding an existing property should have failed\n"); > + > + /* Try to modify an existing property - should pass */ > + prop->value = "modify-property-data-should-pass"; > + prop->length = strlen(prop->value) + 1; > + KUNIT_EXPECT_EQ_MSG( > + test, of_update_property(np, prop), 0, > + "Updating an existing property should have passed\n"); > + > + /* Try to modify non-existent property - should pass*/ > + prop++; > + prop->name = "modify-property"; > + prop->value = "modify-missing-property-data-should-pass"; > + prop->length = strlen(prop->value) + 1; > + KUNIT_EXPECT_EQ_MSG(test, of_update_property(np, prop), 0, > + "Updating a missing property should have passed\n"); > + > + /* Remove property - should pass */ > + KUNIT_EXPECT_EQ_MSG(test, of_remove_property(np, prop), 0, > + "Removing a property should have passed\n"); > + > + /* Adding very large property - should pass */ > + prop++; > + prop->name = "large-property-PAGE_SIZEx8"; > + prop->length = PAGE_SIZE * 8; > + prop->value = kzalloc(prop->length, GFP_KERNEL); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, prop->value); > + KUNIT_EXPECT_EQ_MSG(test, of_add_property(np, prop), 0, > + "Adding a large property should have passed\n"); > +} > + > +static int of_test_init(struct kunit *test) > +{ > + /* adding data for unittest */ > + KUNIT_ASSERT_EQ(test, 0, unittest_data_add()); > + > + if (!of_aliases) > + of_aliases = of_find_node_by_path("/aliases"); > + > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, of_find_node_by_path( > + "/testcase-data/phandle-tests/consumer-a")); > + > + return 0; > +} > + > +static struct kunit_case of_test_cases[] = { > + KUNIT_CASE(of_unittest_find_node_by_name), > + KUNIT_CASE(of_unittest_dynamic), > + {}, > +}; > + > +static struct kunit_module of_test_module = { > + .name = "of-base-test", > + .init = of_test_init, > + .test_cases = of_test_cases, > +}; > +module_test(of_test_module); > diff --git a/drivers/of/test-common.c b/drivers/of/test-common.c > new file mode 100644 > index 0000000000000..4c9a5f3b82f7d > --- /dev/null > +++ b/drivers/of/test-common.c > @@ -0,0 +1,175 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Common code to be used by unit tests. > + */ > +#include "test-common.h" > + > +#include > +#include > + > +#include "of_private.h" > + > +/** > + * update_node_properties - adds the properties > + * of np into dup node (present in live tree) and > + * updates parent of children of np to dup. > + * > + * @np: node whose properties are being added to the live tree > + * @dup: node present in live tree to be updated > + */ > +static void update_node_properties(struct device_node *np, > + struct device_node *dup) > +{ > + struct property *prop; > + struct property *save_next; > + struct device_node *child; > + int ret; > + > + for_each_child_of_node(np, child) > + child->parent = dup; > + > + /* > + * "unittest internal error: unable to add testdata property" > + * > + * If this message reports a property in node '/__symbols__' then > + * the respective unittest overlay contains a label that has the > + * same name as a label in the live devicetree. The label will > + * be in the live devicetree only if the devicetree source was > + * compiled with the '-@' option. If you encounter this error, > + * please consider renaming __all__ of the labels in the unittest > + * overlay dts files with an odd prefix that is unlikely to be > + * used in a real devicetree. > + */ > + > + /* > + * open code for_each_property_of_node() because of_add_property() > + * sets prop->next to NULL > + */ > + for (prop = np->properties; prop != NULL; prop = save_next) { > + save_next = prop->next; > + ret = of_add_property(dup, prop); > + if (ret) > + pr_err("unittest internal error: unable to add testdata property %pOF/%s", > + np, prop->name); > + } > +} > + > +/** > + * attach_node_and_children - attaches nodes > + * and its children to live tree > + * > + * @np: Node to attach to live tree > + */ > +static void attach_node_and_children(struct device_node *np) > +{ > + struct device_node *next, *dup, *child; > + unsigned long flags; > + const char *full_name; > + > + full_name = kasprintf(GFP_KERNEL, "%pOF", np); > + > + if (!strcmp(full_name, "/__local_fixups__") || > + !strcmp(full_name, "/__fixups__")) > + return; > + > + dup = of_find_node_by_path(full_name); > + kfree(full_name); > + if (dup) { > + update_node_properties(np, dup); > + return; > + } > + > + child = np->child; > + np->child = NULL; > + > + mutex_lock(&of_mutex); > + raw_spin_lock_irqsave(&devtree_lock, flags); > + np->sibling = np->parent->child; > + np->parent->child = np; > + of_node_clear_flag(np, OF_DETACHED); > + raw_spin_unlock_irqrestore(&devtree_lock, flags); > + > + __of_attach_node_sysfs(np); > + mutex_unlock(&of_mutex); > + > + while (child) { > + next = child->sibling; > + attach_node_and_children(child); > + child = next; > + } > +} > + > +/** > + * unittest_data_add - Reads, copies data from > + * linked tree and attaches it to the live tree > + */ > +int unittest_data_add(void) > +{ > + void *unittest_data; > + struct device_node *unittest_data_node, *np; > + /* > + * __dtb_testcases_begin[] and __dtb_testcases_end[] are magically > + * created by cmd_dt_S_dtb in scripts/Makefile.lib > + */ > + extern uint8_t __dtb_testcases_begin[]; > + extern uint8_t __dtb_testcases_end[]; > + const int size = __dtb_testcases_end - __dtb_testcases_begin; > + int rc; > + > + if (!size) { > + pr_warn("%s: No testcase data to attach; not running tests\n", > + __func__); > + return -ENODATA; > + } > + > + /* creating copy */ > + unittest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); > + > + if (!unittest_data) { > + pr_warn("%s: Failed to allocate memory for unittest_data; " > + "not running tests\n", __func__); > + return -ENOMEM; > + } > + of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node); > + if (!unittest_data_node) { > + pr_warn("%s: No tree to attach; not running tests\n", __func__); > + return -ENODATA; > + } > + > + /* > + * This lock normally encloses of_resolve_phandles() > + */ > + of_overlay_mutex_lock(); > + > + rc = of_resolve_phandles(unittest_data_node); > + if (rc) { > + pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc); > + of_overlay_mutex_unlock(); > + return -EINVAL; > + } > + > + if (!of_root) { > + of_root = unittest_data_node; > + for_each_of_allnodes(np) > + __of_attach_node_sysfs(np); > + of_aliases = of_find_node_by_path("/aliases"); > + of_chosen = of_find_node_by_path("/chosen"); > + of_overlay_mutex_unlock(); > + return 0; > + } > + > + /* attach the sub-tree to live tree */ > + np = unittest_data_node->child; > + while (np) { > + struct device_node *next = np->sibling; > + > + np->parent = of_root; > + attach_node_and_children(np); > + np = next; > + } > + > + of_overlay_mutex_unlock(); > + > + return 0; > +} > + > diff --git a/drivers/of/test-common.h b/drivers/of/test-common.h > new file mode 100644 > index 0000000000000..a35484406bbf1 > --- /dev/null > +++ b/drivers/of/test-common.h > @@ -0,0 +1,16 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * Common code to be used by unit tests. > + */ > +#ifndef _LINUX_OF_TEST_COMMON_H > +#define _LINUX_OF_TEST_COMMON_H > + > +#include > + > +/** > + * unittest_data_add - Reads, copies data from > + * linked tree and attaches it to the live tree > + */ > +int unittest_data_add(void); > + > +#endif /* _LINUX_OF_TEST_COMMON_H */ > diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c > index 96de69ccb3e63..05a2610d0be7f 100644 > --- a/drivers/of/unittest.c > +++ b/drivers/of/unittest.c > @@ -29,184 +29,7 @@ > #include > > #include "of_private.h" > - > -static void of_unittest_find_node_by_name(struct kunit *test) > -{ > - struct device_node *np; > - const char *options, *name; > - > - np = of_find_node_by_path("/testcase-data"); > - name = kasprintf(GFP_KERNEL, "%pOF", np); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - KUNIT_EXPECT_STREQ_MSG(test, "/testcase-data", name, > - "find /testcase-data failed\n"); > - of_node_put(np); > - kfree(name); > - > - /* Test if trailing '/' works */ > - KUNIT_EXPECT_EQ_MSG(test, of_find_node_by_path("/testcase-data/"), NULL, > - "trailing '/' on /testcase-data/ should fail\n"); > - > - np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - name = kasprintf(GFP_KERNEL, "%pOF", np); > - KUNIT_EXPECT_STREQ_MSG( > - test, "/testcase-data/phandle-tests/consumer-a", name, > - "find /testcase-data/phandle-tests/consumer-a failed\n"); > - of_node_put(np); > - kfree(name); > - > - np = of_find_node_by_path("testcase-alias"); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - name = kasprintf(GFP_KERNEL, "%pOF", np); > - KUNIT_EXPECT_STREQ_MSG(test, "/testcase-data", name, > - "find testcase-alias failed\n"); > - of_node_put(np); > - kfree(name); > - > - /* Test if trailing '/' works on aliases */ > - KUNIT_EXPECT_EQ_MSG(test, of_find_node_by_path("testcase-alias/"), NULL, > - "trailing '/' on testcase-alias/ should fail\n"); > - > - np = of_find_node_by_path("testcase-alias/phandle-tests/consumer-a"); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - name = kasprintf(GFP_KERNEL, "%pOF", np); > - KUNIT_EXPECT_STREQ_MSG( > - test, "/testcase-data/phandle-tests/consumer-a", name, > - "find testcase-alias/phandle-tests/consumer-a failed\n"); > - of_node_put(np); > - kfree(name); > - > - KUNIT_EXPECT_EQ_MSG( > - test, > - np = of_find_node_by_path("/testcase-data/missing-path"), NULL, > - "non-existent path returned node %pOF\n", np); > - of_node_put(np); > - > - KUNIT_EXPECT_EQ_MSG( > - test, np = of_find_node_by_path("missing-alias"), NULL, > - "non-existent alias returned node %pOF\n", np); > - of_node_put(np); > - > - KUNIT_EXPECT_EQ_MSG( > - test, > - np = of_find_node_by_path("testcase-alias/missing-path"), NULL, > - "non-existent alias with relative path returned node %pOF\n", > - np); > - of_node_put(np); > - > - np = of_find_node_opts_by_path("/testcase-data:testoption", &options); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - KUNIT_EXPECT_STREQ_MSG(test, "testoption", options, > - "option path test failed\n"); > - of_node_put(np); > - > - np = of_find_node_opts_by_path("/testcase-data:test/option", &options); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - KUNIT_EXPECT_STREQ_MSG(test, "test/option", options, > - "option path test, subcase #1 failed\n"); > - of_node_put(np); > - > - np = of_find_node_opts_by_path("/testcase-data/testcase-device1:test/option", &options); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - KUNIT_EXPECT_STREQ_MSG(test, "test/option", options, > - "option path test, subcase #2 failed\n"); > - of_node_put(np); > - > - np = of_find_node_opts_by_path("/testcase-data:testoption", NULL); > - KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, np, > - "NULL option path test failed\n"); > - of_node_put(np); > - > - np = of_find_node_opts_by_path("testcase-alias:testaliasoption", > - &options); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - KUNIT_EXPECT_STREQ_MSG(test, "testaliasoption", options, > - "option alias path test failed\n"); > - of_node_put(np); > - > - np = of_find_node_opts_by_path("testcase-alias:test/alias/option", > - &options); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - KUNIT_EXPECT_STREQ_MSG(test, "test/alias/option", options, > - "option alias path test, subcase #1 failed\n"); > - of_node_put(np); > - > - np = of_find_node_opts_by_path("testcase-alias:testaliasoption", NULL); > - KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG( > - test, np, "NULL option alias path test failed\n"); > - of_node_put(np); > - > - options = "testoption"; > - np = of_find_node_opts_by_path("testcase-alias", &options); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - KUNIT_EXPECT_EQ_MSG(test, options, NULL, > - "option clearing test failed\n"); > - of_node_put(np); > - > - options = "testoption"; > - np = of_find_node_opts_by_path("/", &options); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - KUNIT_EXPECT_EQ_MSG(test, options, NULL, > - "option clearing root node test failed\n"); > - of_node_put(np); > -} > - > -static void of_unittest_dynamic(struct kunit *test) > -{ > - struct device_node *np; > - struct property *prop; > - > - np = of_find_node_by_path("/testcase-data"); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); > - > - /* Array of 4 properties for the purpose of testing */ > - prop = kcalloc(4, sizeof(*prop), GFP_KERNEL); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, prop); > - > - /* Add a new property - should pass*/ > - prop->name = "new-property"; > - prop->value = "new-property-data"; > - prop->length = strlen(prop->value) + 1; > - KUNIT_EXPECT_EQ_MSG(test, of_add_property(np, prop), 0, > - "Adding a new property failed\n"); > - > - /* Try to add an existing property - should fail */ > - prop++; > - prop->name = "new-property"; > - prop->value = "new-property-data-should-fail"; > - prop->length = strlen(prop->value) + 1; > - KUNIT_EXPECT_NE_MSG(test, of_add_property(np, prop), 0, > - "Adding an existing property should have failed\n"); > - > - /* Try to modify an existing property - should pass */ > - prop->value = "modify-property-data-should-pass"; > - prop->length = strlen(prop->value) + 1; > - KUNIT_EXPECT_EQ_MSG( > - test, of_update_property(np, prop), 0, > - "Updating an existing property should have passed\n"); > - > - /* Try to modify non-existent property - should pass*/ > - prop++; > - prop->name = "modify-property"; > - prop->value = "modify-missing-property-data-should-pass"; > - prop->length = strlen(prop->value) + 1; > - KUNIT_EXPECT_EQ_MSG(test, of_update_property(np, prop), 0, > - "Updating a missing property should have passed\n"); > - > - /* Remove property - should pass */ > - KUNIT_EXPECT_EQ_MSG(test, of_remove_property(np, prop), 0, > - "Removing a property should have passed\n"); > - > - /* Adding very large property - should pass */ > - prop++; > - prop->name = "large-property-PAGE_SIZEx8"; > - prop->length = PAGE_SIZE * 8; > - prop->value = kzalloc(prop->length, GFP_KERNEL); > - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, prop->value); > - KUNIT_EXPECT_EQ_MSG(test, of_add_property(np, prop), 0, > - "Adding a large property should have passed\n"); > -} > +#include "test-common.h" > > static int of_unittest_check_node_linkage(struct device_node *np) > { > @@ -1177,170 +1000,6 @@ static void of_unittest_platform_populate(struct kunit *test) > of_node_put(np); > } > > -/** > - * update_node_properties - adds the properties > - * of np into dup node (present in live tree) and > - * updates parent of children of np to dup. > - * > - * @np: node whose properties are being added to the live tree > - * @dup: node present in live tree to be updated > - */ > -static void update_node_properties(struct device_node *np, > - struct device_node *dup) > -{ > - struct property *prop; > - struct property *save_next; > - struct device_node *child; > - int ret; > - > - for_each_child_of_node(np, child) > - child->parent = dup; > - > - /* > - * "unittest internal error: unable to add testdata property" > - * > - * If this message reports a property in node '/__symbols__' then > - * the respective unittest overlay contains a label that has the > - * same name as a label in the live devicetree. The label will > - * be in the live devicetree only if the devicetree source was > - * compiled with the '-@' option. If you encounter this error, > - * please consider renaming __all__ of the labels in the unittest > - * overlay dts files with an odd prefix that is unlikely to be > - * used in a real devicetree. > - */ > - > - /* > - * open code for_each_property_of_node() because of_add_property() > - * sets prop->next to NULL > - */ > - for (prop = np->properties; prop != NULL; prop = save_next) { > - save_next = prop->next; > - ret = of_add_property(dup, prop); > - if (ret) > - pr_err("unittest internal error: unable to add testdata property %pOF/%s", > - np, prop->name); > - } > -} > - > -/** > - * attach_node_and_children - attaches nodes > - * and its children to live tree > - * > - * @np: Node to attach to live tree > - */ > -static void attach_node_and_children(struct device_node *np) > -{ > - struct device_node *next, *dup, *child; > - unsigned long flags; > - const char *full_name; > - > - full_name = kasprintf(GFP_KERNEL, "%pOF", np); > - > - if (!strcmp(full_name, "/__local_fixups__") || > - !strcmp(full_name, "/__fixups__")) > - return; > - > - dup = of_find_node_by_path(full_name); > - kfree(full_name); > - if (dup) { > - update_node_properties(np, dup); > - return; > - } > - > - child = np->child; > - np->child = NULL; > - > - mutex_lock(&of_mutex); > - raw_spin_lock_irqsave(&devtree_lock, flags); > - np->sibling = np->parent->child; > - np->parent->child = np; > - of_node_clear_flag(np, OF_DETACHED); > - raw_spin_unlock_irqrestore(&devtree_lock, flags); > - > - __of_attach_node_sysfs(np); > - mutex_unlock(&of_mutex); > - > - while (child) { > - next = child->sibling; > - attach_node_and_children(child); > - child = next; > - } > -} > - > -/** > - * unittest_data_add - Reads, copies data from > - * linked tree and attaches it to the live tree > - */ > -static int unittest_data_add(void) > -{ > - void *unittest_data; > - struct device_node *unittest_data_node, *np; > - /* > - * __dtb_testcases_begin[] and __dtb_testcases_end[] are magically > - * created by cmd_dt_S_dtb in scripts/Makefile.lib > - */ > - extern uint8_t __dtb_testcases_begin[]; > - extern uint8_t __dtb_testcases_end[]; > - const int size = __dtb_testcases_end - __dtb_testcases_begin; > - int rc; > - > - if (!size) { > - pr_warn("%s: No testcase data to attach; not running tests\n", > - __func__); > - return -ENODATA; > - } > - > - /* creating copy */ > - unittest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); > - > - if (!unittest_data) { > - pr_warn("%s: Failed to allocate memory for unittest_data; " > - "not running tests\n", __func__); > - return -ENOMEM; > - } > - of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node); > - if (!unittest_data_node) { > - pr_warn("%s: No tree to attach; not running tests\n", __func__); > - return -ENODATA; > - } > - > - /* > - * This lock normally encloses of_resolve_phandles() > - */ > - of_overlay_mutex_lock(); > - > - rc = of_resolve_phandles(unittest_data_node); > - if (rc) { > - pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc); > - of_overlay_mutex_unlock(); > - return -EINVAL; > - } > - > - if (!of_root) { > - of_root = unittest_data_node; > - for_each_of_allnodes(np) > - __of_attach_node_sysfs(np); > - of_aliases = of_find_node_by_path("/aliases"); > - of_chosen = of_find_node_by_path("/chosen"); > - of_overlay_mutex_unlock(); > - return 0; > - } > - > - /* attach the sub-tree to live tree */ > - np = unittest_data_node->child; > - while (np) { > - struct device_node *next = np->sibling; > - > - np->parent = of_root; > - attach_node_and_children(np); > - np = next; > - } > - > - of_overlay_mutex_unlock(); > - > - return 0; > -} > - > #ifdef CONFIG_OF_OVERLAY > static int overlay_data_apply(const char *overlay_name, int *overlay_id); > > @@ -2563,8 +2222,6 @@ static int of_test_init(struct kunit *test) > static struct kunit_case of_test_cases[] = { > KUNIT_CASE(of_unittest_check_tree_linkage), > KUNIT_CASE(of_unittest_check_phandles), > - KUNIT_CASE(of_unittest_find_node_by_name), > - KUNIT_CASE(of_unittest_dynamic), > KUNIT_CASE(of_unittest_parse_phandle_with_args), > KUNIT_CASE(of_unittest_parse_phandle_with_args_map), > KUNIT_CASE(of_unittest_printf), >