[PATCH 3/3] test: dm: add sandbox coverage for gpio-delay

Pranav Sanwal <[email protected]>
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <[email protected]>
gpio-delay had no sandbox coverage, which is how two bugs in it went
unnoticed: gpio_delay_xlate() never propagated the requested index
into the descriptor offset, so every consumer past the first silently
collided with the first consumer's already-claimed offset 0; and the
claimed/name tracking arrays were sized and bounds-checked against a
hardcoded 32 instead of the driver's actual GPIO count. Both are fixed
by a companion series that is a dependency of this patch: applied
without it, this test fails outright, since it directly exercises
both fixes.

Add a test requesting both consumers wired up by gpio-delay-test in
test.dts (gpio_a 9 and 18): a third consumer colliding with an
already-claimed offset must fail with -EBUSY, each consumer's write
must land on its own wrapped GPIO line, and a request past the
wrapped GPIO count must fail with -EINVAL rather than succeed against
a hardcoded bound of 32.

Gated on CONFIG_GPIO_DELAY, since not every sandbox variant that
builds test/dm/gpio.c enables it (sandbox_vpl, sandbox_spl,
sandbox_noinst, sandbox_flattree).

Signed-off-by: Pranav Sanwal <[email protected]>
---
 test/dm/gpio.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index b872dac9082..17a0dddf083 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -432,6 +432,75 @@ static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_gpio_get_dir_flags, UTF_SCAN_PDATA | UTF_SCAN_FDT);
 
+/*
+ * Test that gpio-delay correctly routes each consumer to its own wrapped
+ * real GPIO line. See gpio-delay-test in test.dts, which wraps gpio_a 9
+ * and gpio_a 18.
+ */
+#if IS_ENABLED(CONFIG_GPIO_DELAY)
+static int dm_test_gpio_delay(struct unit_test_state *uts)
+{
+	struct gpio_desc desc0, desc1, desc2, desc3;
+	struct udevice *dev, *gpio_a;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio_a));
+	ut_asserteq_str("base-gpios", gpio_a->name);
+
+	/*
+	 * Requesting both consumers must succeed. Before the offset was
+	 * propagated in gpio_delay_xlate(), both descriptors came back with
+	 * offset 0, so this second request would fail with -EBUSY as it
+	 * collided with the first consumer's already-claimed offset.
+	 */
+	ut_assertok(gpio_request_by_name(dev, "test6-gpios", 0, &desc0, 0));
+	ut_assertok(gpio_request_by_name(dev, "test6-gpios", 1, &desc1, 0));
+
+	ut_asserteq_ptr(desc0.dev, desc1.dev);
+	ut_asserteq(0, desc0.offset);
+	ut_asserteq(1, desc1.offset);
+
+	/*
+	 * A third consumer mapped to the same offset as the first must be
+	 * rejected as already requested.
+	 */
+	ut_asserteq(-EBUSY, gpio_request_by_name(dev, "test6-gpios", 2, &desc2,
+						 0));
+
+	/*
+	 * Drive each consumer to a different level and confirm the write
+	 * lands on its own wrapped real GPIO line, not the other one's.
+	 * gpio_a has no set_value op of its own (it implements set_flags),
+	 * so dm_gpio_set_value() routes through GPIOD_IS_OUT_ACTIVE.
+	 */
+	ut_assertok(dm_gpio_set_value(&desc0, 0));
+	ut_assertok(dm_gpio_set_value(&desc1, 1));
+	ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 9) & GPIOD_IS_OUT_ACTIVE);
+	ut_asserteq(GPIOD_IS_OUT_ACTIVE,
+		    sandbox_gpio_get_flags(gpio_a, 18) & GPIOD_IS_OUT_ACTIVE);
+
+	ut_assertok(dm_gpio_set_value(&desc0, 1));
+	ut_assertok(dm_gpio_set_value(&desc1, 0));
+	ut_asserteq(GPIOD_IS_OUT_ACTIVE,
+		    sandbox_gpio_get_flags(gpio_a, 9) & GPIOD_IS_OUT_ACTIVE);
+	ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 18) & GPIOD_IS_OUT_ACTIVE);
+
+	ut_assertok(dm_gpio_free(dev, &desc0));
+	ut_assertok(dm_gpio_free(dev, &desc1));
+
+	/*
+	 * An index beyond the wrapped GPIO count (2 here) must be rejected.
+	 * Before gpio_count was set from the "gpios" property, this bound
+	 * was checked against a hardcoded 32 and would have been let through.
+	 */
+	ut_asserteq(-EINVAL, gpio_request_by_name(dev, "test7-gpios", 0, &desc3,
+						  0));
+
+	return 0;
+}
+DM_TEST(dm_test_gpio_delay, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+#endif /* CONFIG_GPIO_DELAY */
+
 /* Test of gpio_get_acpi() */
 static int dm_test_gpio_get_acpi(struct unit_test_state *uts)
 {
-- 
2.43.7
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.