All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [PATCH 17/19] dm: devres: Add tests
Date: Sun, 29 Dec 2019 21:19:26 -0700	[thread overview]
Message-ID: <20191229211913.17.I2cadfd890c935b54af46c4d30a9eeea31b249106@changeid> (raw)
In-Reply-To: <20191230041928.74874-1-sjg@chromium.org>

The devres functionality has very few users in U-Boot, but it still should
have tests. Add a few basic tests of the main functions.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/core/devres.c |  13 +++
 include/dm/devres.h   |  20 +++++
 test/dm/Makefile      |   1 +
 test/dm/devres.c      | 178 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 212 insertions(+)
 create mode 100644 test/dm/devres.c

diff --git a/drivers/core/devres.c b/drivers/core/devres.c
index 9c04499c6d..36a8b1eb5f 100644
--- a/drivers/core/devres.c
+++ b/drivers/core/devres.c
@@ -223,6 +223,19 @@ void dm_dump_devres(void)
 	if (root)
 		dump_resources(root, 0);
 }
+
+void devres_get_stats(const struct udevice *dev, struct devres_stats *stats)
+{
+	struct devres *dr;
+
+	stats->allocs = 0;
+	stats->total_size = 0;
+	list_for_each_entry(dr, &dev->devres_head, entry) {
+		stats->allocs++;
+		stats->total_size += dr->size;
+	}
+}
+
 #endif
 
 /*
diff --git a/include/dm/devres.h b/include/dm/devres.h
index 32fbf38054..9c69196054 100644
--- a/include/dm/devres.h
+++ b/include/dm/devres.h
@@ -15,6 +15,17 @@
 typedef void (*dr_release_t)(struct udevice *dev, void *res);
 typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
 
+/**
+ * struct devres_stats - Information about devres allocations for a device
+ *
+ * @allocs: Number of allocations
+ * @total_size: Total size of allocations in bytes
+ */
+struct devres_stats {
+	int allocs;
+	int total_size;
+};
+
 #ifdef CONFIG_DEVRES
 
 #ifdef CONFIG_DEBUG_DEVRES
@@ -189,6 +200,9 @@ static inline void *devm_kcalloc(struct udevice *dev,
  */
 void devm_kfree(struct udevice *dev, void *ptr);
 
+/* Get basic stats on allocations */
+void devres_get_stats(const struct udevice *dev, struct devres_stats *stats);
+
 #else /* ! CONFIG_DEVRES */
 
 static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
@@ -265,5 +279,11 @@ static inline void devm_kfree(struct udevice *dev, void *ptr)
 {
 	kfree(ptr);
 }
+
+static inline void devres_get_stats(const struct udevice *dev,
+				    struct devres_stats *stats)
+{
+}
+
 #endif /* DEVRES */
 #endif /* _DM_DEVRES_H */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index a268783169..85cc0f7fb8 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_BLK) += blk.o
 obj-$(CONFIG_BOARD) += board.o
 obj-$(CONFIG_DM_BOOTCOUNT) += bootcount.o
 obj-$(CONFIG_CLK) += clk.o clk_ccf.o
+obj-$(CONFIG_DEVRES) += devres.o
 obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi_host.o
 obj-$(CONFIG_DM_ETH) += eth.o
 obj-$(CONFIG_FIRMWARE) += firmware.o
diff --git a/test/dm/devres.c b/test/dm/devres.c
new file mode 100644
index 0000000000..c351844db9
--- /dev/null
+++ b/test/dm/devres.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for the devres (
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <malloc.h>
+#include <dm/device-internal.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <test/ut.h>
+
+/* Test that devm_kmalloc() allocates memory, free when device is removed */
+static int dm_test_devres_alloc(struct unit_test_state *uts)
+{
+	ulong mem_start, mem_dev, mem_kmalloc;
+	struct udevice *dev;
+	void *ptr;
+
+	mem_start = ut_check_delta(0);
+	ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
+	mem_dev = ut_check_delta(mem_start);
+	ut_assert(mem_dev > 0);
+
+	/* This should increase allocated memory */
+	ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
+	ut_assert(ptr != NULL);
+	mem_kmalloc = ut_check_delta(mem_dev);
+	ut_assert(mem_kmalloc > 0);
+
+	/* Check that ptr is freed */
+	device_remove(dev, DM_REMOVE_NORMAL);
+	ut_asserteq(0, ut_check_delta(mem_start));
+
+	return 0;
+}
+DM_TEST(dm_test_devres_alloc, DM_TESTF_SCAN_PDATA);
+
+/* Test devm_kfree() can be used to free memory too */
+static int dm_test_devres_free(struct unit_test_state *uts)
+{
+	ulong mem_start, mem_dev, mem_kmalloc;
+	struct udevice *dev;
+	void *ptr;
+
+	mem_start = ut_check_delta(0);
+	ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
+	mem_dev = ut_check_delta(mem_start);
+	ut_assert(mem_dev > 0);
+
+	ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
+	ut_assert(ptr != NULL);
+	mem_kmalloc = ut_check_delta(mem_dev);
+	ut_assert(mem_kmalloc > 0);
+
+	/* Free the ptr and check that memory usage goes down */
+	devm_kfree(dev, ptr);
+	ut_assert(ut_check_delta(mem_kmalloc) < 0);
+
+	device_remove(dev, DM_REMOVE_NORMAL);
+	ut_asserteq(0, ut_check_delta(mem_start));
+
+	return 0;
+}
+DM_TEST(dm_test_devres_free, DM_TESTF_SCAN_PDATA);
+
+
+/* Test that kzalloc() returns memory that is zeroed */
+static int dm_test_devres_kzalloc(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	u8 *ptr, val;
+	int i;
+
+	ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
+
+	ptr = devm_kzalloc(dev, TEST_DEVRES_SIZE, 0);
+	ut_assert(ptr != NULL);
+	for (val = 0, i = 0; i < TEST_DEVRES_SIZE; i++)
+		val |= *ptr;
+	ut_asserteq(0, val);
+
+	return 0;
+}
+DM_TEST(dm_test_devres_kzalloc, DM_TESTF_SCAN_PDATA);
+
+/* Test that devm_kmalloc_array() allocates an array that can be set */
+static int dm_test_devres_kmalloc_array(struct unit_test_state *uts)
+{
+	ulong mem_start, mem_dev;
+	struct udevice *dev;
+	u8 *ptr;
+
+	mem_start = ut_check_delta(0);
+	ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
+	mem_dev = ut_check_delta(mem_start);
+
+	ptr = devm_kmalloc_array(dev, TEST_DEVRES_COUNT, TEST_DEVRES_SIZE, 0);
+	ut_assert(ptr != NULL);
+	memset(ptr, '\xff', TEST_DEVRES_TOTAL);
+	ut_assert(ut_check_delta(mem_dev) > 0);
+
+	device_remove(dev, DM_REMOVE_NORMAL);
+	ut_asserteq(0, ut_check_delta(mem_start));
+
+	return 0;
+}
+DM_TEST(dm_test_devres_kmalloc_array, DM_TESTF_SCAN_PDATA);
+
+/* Test that devm_kcalloc() allocates a zeroed array */
+static int dm_test_devres_kcalloc(struct unit_test_state *uts)
+{
+	ulong mem_start, mem_dev;
+	struct udevice *dev;
+	u8 *ptr, val;
+	int i;
+
+	mem_start = ut_check_delta(0);
+	ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
+	mem_dev = ut_check_delta(mem_start);
+	ut_assert(mem_dev > 0);
+
+	/* This should increase allocated memory */
+	ptr = devm_kcalloc(dev, TEST_DEVRES_SIZE, TEST_DEVRES_COUNT, 0);
+	ut_assert(ptr != NULL);
+	ut_assert(ut_check_delta(mem_dev) > 0);
+	for (val = 0, i = 0; i < TEST_DEVRES_TOTAL; i++)
+		val |= *ptr;
+	ut_asserteq(0, val);
+
+	/* Check that ptr is freed */
+	device_remove(dev, DM_REMOVE_NORMAL);
+	ut_asserteq(0, ut_check_delta(mem_start));
+
+	return 0;
+}
+DM_TEST(dm_test_devres_kcalloc, DM_TESTF_SCAN_PDATA);
+
+static int dm_test_devres_phase(struct unit_test_state *uts)
+{
+	struct devres_stats stats;
+	struct udevice *dev;
+
+	/*
+	 * The device is bound already, so find it and check that it has the
+	 * allocation created in the bind() method.
+	 */
+	ut_assertok(uclass_find_first_device(UCLASS_TEST_DEVRES, &dev));
+	devres_get_stats(dev, &stats);
+	ut_asserteq(1, stats.allocs);
+	ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
+
+	/* Probing the device should add one allocation */
+	ut_assertok(uclass_first_device(UCLASS_TEST_DEVRES, &dev));
+	ut_assert(dev != NULL);
+	devres_get_stats(dev, &stats);
+	ut_asserteq(2, stats.allocs);
+	ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2, stats.total_size);
+
+	/* Removing the device should drop one allocation */
+	device_remove(dev, DM_REMOVE_NORMAL);
+	devres_get_stats(dev, &stats);
+	ut_asserteq(1, stats.allocs);
+	ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
+
+	/* Unbinding removes the other. Note this access a freed pointer */
+	device_unbind(dev);
+	devres_get_stats(dev, &stats);
+	ut_asserteq(0, stats.allocs);
+	ut_asserteq(0, stats.total_size);
+
+	return 0;
+}
+DM_TEST(dm_test_devres_phase, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-- 
2.24.1.735.g03f4e72817-goog

  parent reply	other threads:[~2019-12-30  4:19 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-30  4:19 [PATCH 00/19] dm: core: Fully separate ofdata_to_platdata() from probe() Simon Glass
2019-12-30  4:19 ` [PATCH 01/19] common: Add a noisy assert() Simon Glass
2019-12-30  4:19 ` [PATCH 02/19] dm: core: Use assert_noisy() in devres Simon Glass
2019-12-30  4:19 ` [PATCH 03/19] usb: Drop use of BUG_ON() and WARN_ON() Simon Glass
2019-12-30  4:19 ` [PATCH 04/19] x86: apl: Avoid accessing the PCI bus before it is probed Simon Glass
2019-12-30  4:19 ` [PATCH 05/19] pci: Print a warning if the bus is accessed before probing Simon Glass
2019-12-30  4:19 ` [PATCH 06/19] aspeed: ast2500: Read clock ofdata in the correct method Simon Glass
2020-01-07  8:20   ` Cédric Le Goater
2020-01-09 20:04     ` Simon Glass
2020-01-10  8:57     ` sjg at google.com
2019-12-30  4:19 ` [PATCH 07/19] dm: core: Don't clear active flag twice when probe() fails Simon Glass
2019-12-30  4:19 ` [PATCH 08/19] dm: core: Move ofdata_to_platdata() call earlier Simon Glass
2019-12-30  4:19 ` [PATCH 09/19] dm: core: Allocate parent data separate from probing parent Simon Glass
2019-12-30  4:19 ` [PATCH 10/19] dm: core: Add a comment for DM_FLAG_OF_PLATDATA Simon Glass
2019-12-30  4:19 ` [PATCH 11/19] dm: core: Export a new function to read platdata Simon Glass
2019-12-30  4:19 ` [PATCH 12/19] dm: core: Add a new flag to track platform data Simon Glass
2019-12-30  4:19 ` [PATCH 13/19] dm: devres: Create a new devres header file Simon Glass
2019-12-30  4:19 ` [PATCH 14/19] test: Add functions to find the amount of allocated memory Simon Glass
2019-12-30  4:19 ` [PATCH 15/19] dm: devres: Convert to use logging Simon Glass
2019-12-30  4:19 ` [PATCH 16/19] dm: test: Add a test driver for devres Simon Glass
2019-12-30  4:19 ` Simon Glass [this message]
2019-12-30  4:19 ` [PATCH 18/19] dm: devres: Use an enum for the allocation phase Simon Glass
2019-12-30  4:19 ` [PATCH 19/19] dm: devres: Add a new OFDATA phase Simon Glass
2020-01-10  8:57 ` [PATCH 18/19] dm: devres: Use an enum for the allocation phase sjg at google.com
2020-01-10  8:57 ` [PATCH 19/19] dm: devres: Add a new OFDATA phase sjg at google.com
2020-01-10  8:57 ` [PATCH 17/19] dm: devres: Add tests sjg at google.com
2020-01-10  8:57 ` [PATCH 16/19] dm: test: Add a test driver for devres sjg at google.com
2020-01-10  8:57 ` [PATCH 14/19] test: Add functions to find the amount of allocated memory sjg at google.com
2020-01-10  8:57 ` [PATCH 15/19] dm: devres: Convert to use logging sjg at google.com
2020-01-10  8:57 ` [PATCH 13/19] dm: devres: Create a new devres header file sjg at google.com
2020-01-10  8:57 ` [PATCH 12/19] dm: core: Add a new flag to track platform data sjg at google.com
2020-01-10  8:57 ` [PATCH 11/19] dm: core: Export a new function to read platdata sjg at google.com
2020-01-10  8:57 ` [PATCH 10/19] dm: core: Add a comment for DM_FLAG_OF_PLATDATA sjg at google.com
2020-01-10  8:57 ` [PATCH 09/19] dm: core: Allocate parent data separate from probing parent sjg at google.com
2020-01-10  8:57 ` [PATCH 08/19] dm: core: Move ofdata_to_platdata() call earlier sjg at google.com
2020-01-10  8:57 ` [PATCH 07/19] dm: core: Don't clear active flag twice when probe() fails sjg at google.com
2020-01-10  8:57 ` [PATCH 05/19] pci: Print a warning if the bus is accessed before probing sjg at google.com
2020-01-10  8:57 ` [PATCH 04/19] x86: apl: Avoid accessing the PCI bus before it is probed sjg at google.com
2020-01-10  8:57 ` [PATCH 03/19] usb: Drop use of BUG_ON() and WARN_ON() sjg at google.com
2020-01-10  8:57 ` [PATCH 02/19] dm: core: Use assert_noisy() in devres sjg at google.com
2020-01-10  8:57 ` [PATCH 01/19] common: Add a noisy assert() sjg at google.com

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191229211913.17.I2cadfd890c935b54af46c4d30a9eeea31b249106@changeid \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.