[U-Boot] [PATCH] py: test_gpio: Add support for GPIO pytest
Stephen Warren
swarren at wwwdotorg.org
Wed Sep 20 17:05:25 UTC 2017
On 09/20/2017 01:55 AM, Michal Simek wrote:
> From: Vipul Kumar <vipul.kumar at xilinx.com>
>
> This patch tests the gpio commands using the
> gpio data from boardenv file.
>
> Also one test will show the default status of all the gpio's
> supported by the processor.
Nit: Wrap the commit description to something like 74 characters; the
text above is far too narrow.
Nit: GPIO not gpio in any free-form text (here and in comments in the
source file)
Ah, I'd briefly though about GPIO tests before, but was wondering how to
integrate e.g. a USB GPIO device to the host PC and interface that with
the target. Loopback GPIOs make this a lot easier:-)
> diff --git a/test/py/tests/test_gpio.py b/test/py/tests/test_gpio.py
> +"""
> +Note: This test relies on boardenv_* containing configuration values to define
> +which the gpio available for testing. Without this, this test will be automat-
Nit: Double space before automatically.
> +For example:
> +
> +# A list of gpio's that are going to be tested in order to validate the
> +# test.
> +env__gpio_val = {
> + "gpio": [0,1,2],
> +}
Why is this a dictionary with only one key? Better to just assign the
array directly to env__gpio_val, or put both the "gpio" and
"list_of_gpios" into a single dictionary.
> +# A list of gpio's that are shorted on the hardware board and first gpio of
> +# each group is configured as input and the other as output. If the pins are
> +# not shorted properly, then the test will be fail.
> +env__gpio_input_output = {
> + "list_of_gpios": [ [36, 37], [38, 39]],
> +}
Let's make the examples for env__gpio_val and env__gpio_input_output use
the same GPIO numbers so that they match, and it's obvious how the two
relate to each-other. I assume they're meant to?
Actually, why do we even need env__gpio_val if env__gpio_input_output
already lists all the pairs of GPIOs?
Again, let's collapse this dict/list pair into just a list without the
dict wrapper.
"gpio_val", "gpio", "gpio_input_output", and "list_of_gpios" aren't
exactly great names. At least for "gpio_input_output"/"list_of_gpios",
I'd suggest a more semantic name is "env__looped_back_gpios", which is a
plain list (of pairs of GPIO numbers).
> +def gpio_input(u_boot_console, gpio):
> + u_boot_console.run_command("gpio input %d" %gpio)
Nit: Space after % operator (the second % outside the string). Same
comment in many other cases.
> + response = u_boot_console.run_command("gpio status -a %d" %gpio)
> + expected_response = "%d: input:" %gpio
> + assert(expected_response in response)
> +
> +def gpio_set(u_boot_console, gpio):
> + expected_response = "%d: output: 1" %gpio
> + u_boot_console.run_command("gpio set %d" %gpio)
> + response = u_boot_console.run_command("gpio status -a %d" %gpio)
> + assert(expected_response in response)
Why not make all these functions do things in the same order;
gpio_input() above sets expected_response immediately before the assert
(which I think is the right place to do it since it relates to the
assert and not the gpio set/clear/toggle command which is executed
earlier), whereas the other functions set expected_response at the start
of the function.
> + at pytest.mark.buildconfigspec("cmd_gpio")
> +def test_gpio_status(u_boot_console):
> + response = u_boot_console.run_command("gpio status -a")
> + expected_response = "0: input:"
> + assert(expected_response in response)
This test assumes that GPIO 0 is expected to be configured as an input
by default (at boot) on all HW that supports GPIOs. I don't think this
is a valid assumption.
> + at pytest.mark.buildconfigspec("cmd_gpio")
> +def test_gpio(u_boot_console):
> + f = u_boot_console.config.env.get('env__gpio_val', None)
> + if not f:
> + pytest.skip('No GPIO readable file to read')
What "file" is this referring to? A better message might be
'env__gpio_val not defined for this board'.
> + gpin = f.get("gpio", None)
> +
> + for gpio in gpin:
> + gpio_input(u_boot_console, gpio)
> + gpio_set(u_boot_console, gpio)
> + gpio_clear(u_boot_console, gpio)
> + gpio_toggle(u_boot_console, gpio)
So this is simply to test executing those commands? Why not rely on
testing them as a side-effect of the loopback test below? the only one
untested is toggle, and that could be added to the loopback test.
> + at pytest.mark.buildconfigspec("cmd_gpio")
> +def test_gpio_input_output(u_boot_console):
> + f = u_boot_console.config.env.get('env__gpio_input_output', None)
> + if not f:
> + pytest.skip('No GPIO readable file to read')
> +
> + list_of_gpios = f.get("list_of_gpios", None)
> +
> + flag = 0
> + for list in list_of_gpios:
> + for i in list:
> + if flag == 0:
> + gpio_in = i
> + expected_response = "%d: input:" %gpio_in
> + u_boot_console.run_command("gpio input %d" %gpio_in)
> + response = u_boot_console.run_command("gpio status -a %d" %gpio_in)
> + assert(expected_response in response)
> + flag = 1
> +
> + else:
> + gpio_out = i
> + expected_response = "%d: output:" %gpio_out
> + u_boot_console.run_command("gpio set %d" %gpio_out)
> + response = u_boot_console.run_command("gpio status -a %d" %gpio_out)
> + assert(expected_response in response)
> + flag = 0
This (the inner "for i in list") doesn't need to be a loop, since it's
using flag to do completely different things on each iteration anyway,
and that logic is pretty confusing. Instead, just do:
for list in list_of_gpios:
gpio_in = list[0]
configure input GPIO
gpio_out = list[1]
set gpio_out to 0
validate gpio_in value is 0
set gpio_out to 1
validate gpio_in value is 1
(and "list" isn't a great variable name especially since it aliases with
a Python type constructor function; gpio_pair would be better)
... and actually it might be better to do something like the following:
for every GPIO pair:
set gpio_in to input
for every GPIO pair:
set gpio_out to 0
for every GPIO pair:
set gpio_out to 1
for every GPIO pair:
if inner gpio_in == output gpio_in:
expected_val = 1
else:
expected_val = 0
validate inner gpio_in is expected_val
set gpio_out to 0
... since that will both test that each gpio_out value affects the
associated gpio_in value, but also that no gpio_out value affects any
unexpected/unassociated gpio_in value.
More information about the U-Boot
mailing list