All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lukasz Majewski <l.majewski@samsung.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 8/8] test/py: add DFU test
Date: Thu, 21 Jan 2016 11:50:00 +0100	[thread overview]
Message-ID: <20160121115000.3782cdb5@amdc2363> (raw)
In-Reply-To: <1453328158-23818-8-git-send-email-swarren@wwwdotorg.org>

Hi Stephen,

> From: Stephen Warren <swarren@nvidia.com>
> 
> Add a test of DFU functionality to the Python test suite. The test
> starts DFU in U-Boot, waits for USB device enumeration on the host,
> executes dfu-util multiple times to test various transfer sizes, many
> of which trigger USB driver edge cases, and finally aborts the DFU
> command in U-Boot.
> 
> This test mirrors the functionality previously available via the shell
> scripts in test/dfu, and hence those are removed too.
> 
> Cc: Lukasz Majewski <l.majewski@majess.pl>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
>  test/dfu/README                  |  44 -------
>  test/dfu/dfu_gadget_test.sh      | 108 ----------------
>  test/dfu/dfu_gadget_test_init.sh |  45 -------
>  test/py/tests/test_dfu.py        | 257
> +++++++++++++++++++++++++++++++++++++++ 4 files changed, 257
> insertions(+), 197 deletions(-) delete mode 100644 test/dfu/README
>  delete mode 100755 test/dfu/dfu_gadget_test.sh
>  delete mode 100755 test/dfu/dfu_gadget_test_init.sh
>  create mode 100644 test/py/tests/test_dfu.py
> 
> diff --git a/test/dfu/README b/test/dfu/README
> deleted file mode 100644
> index 408d5594219a..000000000000
> --- a/test/dfu/README
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -DFU TEST CASE DESCRIPTION:
> -
> -The prerequisites for running this script are assured by
> -dfu_gadget_test_init.sh, which is automatically invoked by
> dfu_gadget_test.sh. -In this file user is able to generate their own
> set of test files by altering -the default set of TEST_FILES_SIZES
> variable. -The dfu_gadget_test_init.sh would generate test images
> only if they are not -already generated.
> -
> -On the target device, environment variable "dfu_alt_info" must
> contain at -least:
> -
> -    dfu_test.bin fat 0 6;dfudummy.bin fat 0 6
> -
> -Depending on your device, you may need to replace "fat" with
> -"ext4", and "6" with the relevant partition number. For reference
> please -consult the config file for TRATS/TRATS2 devices
> -(../../include/configs/trats{2}.h)
> -
> -One can use fat, ext4 or any other supported file system supported
> by U-Boot. -These can be created by exporting storage devices via UMS
> (ums 0 mmc 0) and -using standard tools on host (like mkfs.ext4).
> -
> -Example usage:
> -1. On the target:
> -   setenv dfu_alt_info dfu_test.bin fat 0 6\;dfudummy.bin fat 0 6
> -   dfu 0 mmc 0
> -2. On the host:
> -   test/dfu/dfu_gadget_test.sh X Y [test file name] [usb device
> vendor:product]
> -   e.g. test/dfu/dfu_gadget_test.sh 0 1
> -   or
> -   e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img
> -   or
> -   e.g. test/dfu/dfu_gadget_test.sh 0 1 0451:d022
> -   or
> -   e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img 0451:d022
> -
> -... where X and Y are dfu_test.bin's and dfudummy.bin's alt setting
> numbers. -They can be obtained from dfu-util -l or $dfu_alt_info.
> -It is also possible to pass optional [test file name] to force the
> script to -test one particular file.
> -If many DFU devices are connected, it may be useful to filter on USB
> -vendor/product ID (0451:d022).
> -One can get them by running "lsusb" command on a host PC.
> diff --git a/test/dfu/dfu_gadget_test.sh b/test/dfu/dfu_gadget_test.sh
> deleted file mode 100755
> index 9c7942257b44..000000000000
> --- a/test/dfu/dfu_gadget_test.sh
> +++ /dev/null
> @@ -1,108 +0,0 @@
> -#! /bin/bash
> -
> -# Copyright (C) 2014 Samsung Electronics
> -# Lukasz Majewski <l.majewski@samsung.com>
> -#
> -# Script fixes, enhancements and testing:
> -# Stephen Warren <swarren@nvidia.com>
> -#
> -# DFU operation test script
> -#
> -# SPDX-License-Identifier:	GPL-2.0+
> -
> -set -e # any command return if not equal to zero
> -clear
> -
> -COLOUR_RED="\33[31m"
> -COLOUR_GREEN="\33[32m"
> -COLOUR_DEFAULT="\33[0m"
> -
> -DIR=./
> -SUFFIX=img
> -RCV_DIR=rcv/
> -LOG_FILE=./log/log-`date +%d-%m-%Y_%H-%M-%S`
> -
> -cd `dirname $0`
> -./dfu_gadget_test_init.sh
> -
> -cleanup () {
> -    rm -rf $DIR$RCV_DIR
> -}
> -
> -die () {
> -	printf "   $COLOUR_RED FAILED $COLOUR_DEFAULT \n"
> -	cleanup
> -	exit 1
> -}
> -
> -calculate_md5sum () {
> -    MD5SUM=`md5sum $1`
> -    MD5SUM=`echo $MD5SUM | cut -d ' ' -f1`
> -    echo "md5sum:"$MD5SUM
> -}
> -
> -dfu_test_file () {
> -    printf "$COLOUR_GREEN
> =========================================================================================
> $COLOUR_DEFAULT\n"
> -    printf "File:$COLOUR_GREEN %s $COLOUR_DEFAULT\n" $1
> -
> -    dfu-util $USB_DEV -D $1 -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1
> || die $? -
> -    echo -n "TX: "
> -    calculate_md5sum $1
> -
> -    MD5_TX=$MD5SUM
> -
> -    dfu-util $USB_DEV -D ${DIR}/dfudummy.bin -a
> $TARGET_ALT_SETTING_B >> $LOG_FILE 2>&1 || die $? -
> -    N_FILE=$DIR$RCV_DIR${1:2}"_rcv"
> -
> -    dfu-util $USB_DEV -U $N_FILE -a $TARGET_ALT_SETTING >> $LOG_FILE
> 2>&1 || die $? -
> -    echo -n "RX: "
> -    calculate_md5sum $N_FILE
> -    MD5_RX=$MD5SUM
> -
> -    if [ "$MD5_TX" == "$MD5_RX" ]; then
> -	printf "   $COLOUR_GREEN -------> OK $COLOUR_DEFAULT \n"
> -    else
> -	printf "   $COLOUR_RED -------> FAILED $COLOUR_DEFAULT \n"
> -	cleanup
> -	exit 1
> -    fi
> -
> -}
> -
> -printf
> "$COLOUR_GREEN=========================================================================================
> $COLOUR_DEFAULT\n" -echo "DFU EP0 transmission test program" -echo
> "Trouble shoot -> disable DBG (even the KERN_DEBUG) in the UDC
> driver" -echo "@ -> TRATS2 # dfu 0 mmc 0" -cleanup
> -mkdir -p $DIR$RCV_DIR
> -touch $LOG_FILE
> -
> -if [ $# -eq 0 ]
> -then
> -	printf "   $COLOUR_RED Please pass alt setting number!!
> $COLOUR_DEFAULT \n"
> -	exit 0
> -fi
> -
> -TARGET_ALT_SETTING=$1
> -TARGET_ALT_SETTING_B=$2
> -
> -file=$3
> -[[ $3 == *':'* ]] && USB_DEV="-d $3" && file=""
> -[ $# -eq 4 ] && USB_DEV="-d $4"
> -
> -if [ -n "$file" ]
> -then
> -	dfu_test_file $file
> -else
> -	for f in $DIR*.$SUFFIX
> -	do
> -	    dfu_test_file $f
> -	done
> -fi
> -
> -cleanup
> -
> -exit 0
> diff --git a/test/dfu/dfu_gadget_test_init.sh
> b/test/dfu/dfu_gadget_test_init.sh deleted file mode 100755
> index 640628eecb7a..000000000000
> --- a/test/dfu/dfu_gadget_test_init.sh
> +++ /dev/null
> @@ -1,45 +0,0 @@
> -#! /bin/bash
> -
> -# Copyright (C) 2014 Samsung Electronics
> -# Lukasz Majewski <l.majewski@samsung.com>
> -#
> -# Script fixes, enhancements and testing:
> -# Stephen Warren <swarren@nvidia.com>
> -#
> -# Script for test files generation
> -#
> -# SPDX-License-Identifier:	GPL-2.0+
> -
> -set -e # any command return if not equal to zero
> -clear
> -
> -COLOUR_RED="\33[31m"
> -COLOUR_GREEN="\33[32m"
> -COLOUR_DEFAULT="\33[0m"
> -
> -LOG_DIR="./log"
> -
> -if [ $# -eq 0 ]; then
> -    TEST_FILES_SIZES="63 64 65 127 128 129 4095 4096 4097 959 960
> 961 1048575 1048576 8M" -else
> -    TEST_FILES_SIZES=$@
> -fi
> -
> -printf "Init script for generating data necessary for DFU test
> script" -
> -if [ ! -d $LOG_DIR ]; then
> -    `mkdir $LOG_DIR`
> -fi
> -
> -for size in $TEST_FILES_SIZES
> -do
> -    FILE="./dat_$size.img"
> -    if [ ! -f $FILE ]; then
> -	dd if=/dev/urandom of="./dat_$size.img" bs=$size count=1
> > /dev/null 2>&1 || exit $?
> -    fi
> -done
> -dd if=/dev/urandom of="./dfudummy.bin" bs=1024 count=1 > /dev/null
> 2>&1 || exit $? -
> -printf "$COLOUR_GREEN OK $COLOUR_DEFAULT \n"
> -
> -exit 0
> diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py
> new file mode 100644
> index 000000000000..e86ea9a1887c
> --- /dev/null
> +++ b/test/py/tests/test_dfu.py
> @@ -0,0 +1,257 @@
> +# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
> +#
> +# SPDX-License-Identifier: GPL-2.0
> +
> +# Test U-Boot's "ums" command. At present, this test only ensures
> that a UMS +# device can be enumerated by the host/test machine. In
> the future, this test +# should be enhanced to validate disk IO.

Please update this comment to regard dfu, not ums.

> +
> +import os
> +import os.path
> +import pytest
> +import u_boot_utils
> +
> +'''
> +Note: This test relies on:
> +
> +a) boardenv_* to contain configuration values to define which USB
> ports are +available for testing. Without this, this test will be
> automatically skipped. +For example:
> +
> +env__usb_dev_ports = (
> +    {
> +        "tgt_usb_ctlr": "0",
> +        "host_usb_dev_node": "/dev/usbdev-p2371-2180",
> +        # This parameter is optional /if/ you only have a single
> board
> +        # attached to your host at a time.
> +        "host_usb_port_path": "3-13",
> +    },
> +)
> +
> +env__dfu_configs = (
> +    # eMMC, partition 1
> +    {
> +        "alt_info": "/dfu_test.bin ext4 0 1;/dfu_dummy.bin ext4 0 1",
> +        "cmd_params": "mmc 0",
> +    },
> +)
> +b) udev rules to set permissions on devices nodes, so that sudo is
> not +required. For example:
> +
> +ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb",
> KERNELS=="3-13", MODE:="666" +
> +(You may wish to change the group ID instead of setting the
> permissions wide +open. All that matters is that the user ID running
> the test can access the +device.)
> +'''
> +
> +# The set of file sizes to test. These values trigger various
> edge-cases such +# as one less than, equal to, and one greater than
> typical USB max packet +# sizes, and similar boundary conditions.
> +test_sizes = (
> +    64 - 1,
> +    64,
> +    64 + 1,
> +    128 - 1,
> +    128,
> +    128 + 1,
> +    960 - 1,
> +    960,
> +    960 + 1,
> +    4096 - 1,
> +    4096,
> +    4096 + 1,
> +    1024 * 1024 - 1,
> +    1024 * 1024,
> +    8 * 1024 * 1024,
> +)
> +
> +first_usb_dev_port = None
> +
> + at pytest.mark.buildconfigspec('cmd_dfu')
> +def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
> +    '''Test DFU functionality, using numerous file sizes.
> +
> +    Args:
> +        u_boot_console: A U-Boot console connection.
> +        env__usb_dev_port: The single USB device-mode port
> specification on
> +            which to run the test.
> +        env__dfu_config: The single DFU (memory region)
> configuration on which
> +            to run the test.
> +
> +    Returns:
> +        Nothing.
> +    '''
> +
> +    def start_dfu():
> +        '''Start U-Boot's dfu shell command.
> +
> +        This also waits for the host-side USB enumeration process to
> complete. +
> +        Args:
> +            None.
> +
> +        Returns:
> +            Nothing.
> +        '''
> +
> +        u_boot_console.log.action(
> +            'Starting long-running U-Boot dfu shell command')
> +
> +        cmd = 'setenv dfu_alt_info "%s"' %
> env__dfu_config['alt_info']
> +        u_boot_console.run_command(cmd)
> +
> +        cmd = 'dfu 0 ' + env__dfu_config['cmd_params']
> +        u_boot_console.run_command(cmd, wait_for_prompt=False)
> +        u_boot_console.log.action('Waiting for DFU USB device to
> appear')
> +        fh = u_boot_utils.wait_until_open_succeeds(
> +            env__usb_dev_port['host_usb_dev_node'])
> +        fh.close()
> +
> +    def stop_dfu(ignore_errors):
> +        '''Stop U-Boot's dfu shell command from executing.
> +
> +        This also waits for the host-side USB de-enumeration process
> to
> +        complete.
> +
> +        Args:
> +            ignore_errors: Ignore any errors. This is useful if an
> error has
> +                already been detected, and the code is performing
> best-effort
> +                cleanup. In this case, we do not want to mask the
> original
> +                error by "honoring" any new errors.
> +
> +        Returns:
> +            Nothing.
> +        '''
> +
> +        try:
> +            u_boot_console.log.action(
> +                'Stopping long-running U-Boot dfu shell command')
> +            u_boot_console.ctrlc()
> +            u_boot_console.log.action(
> +                'Waiting for DFU USB device to disappear')
> +            u_boot_utils.wait_until_file_open_fails(
> +                env__usb_dev_port['host_usb_dev_node'],
> ignore_errors)
> +        except:
> +            if not ignore_errors:
> +                raise
> +
> +    def run_dfu_util(alt_setting, fn, up_dn_load_arg):
> +        '''Invoke dfu-util on the host.
> +
> +        Args:
> +            alt_setting: The DFU "alternate setting" identifier to
> interact
> +                with.
> +            fn: The host-side file name to transfer.
> +            up_dn_load_arg: '-U' or '-D' depending on whether a DFU
> upload or
> +                download operation should be performed.
> +
> +        Returns:
> +            Nothing.
> +        '''
> +
> +        cmd = ['dfu-util', '-a', str(alt_setting), up_dn_load_arg,
> fn]
> +        if 'host_usb_port_path' in env__usb_dev_port:
> +            cmd += ['-p', env__usb_dev_port['host_usb_port_path']]
> +        u_boot_utils.run_and_log(u_boot_console, cmd)
> +        u_boot_console.wait_for('Ctrl+C to exit ...')
> +
> +    def dfu_write(alt_setting, fn):
> +        '''Write a file to the target board using DFU.
> +
> +        Args:
> +            alt_setting: The DFU "alternate setting" identifier to
> interact
> +                with.
> +            fn: The host-side file name to transfer.
> +
> +        Returns:
> +            Nothing.
> +        '''
> +
> +        run_dfu_util(alt_setting, fn, '-D')
> +
> +    def dfu_read(alt_setting, fn):
> +        '''Read a file from the target board using DFU.
> +
> +        Args:
> +            alt_setting: The DFU "alternate setting" identifier to
> interact
> +                with.
> +            fn: The host-side file name to transfer.
> +
> +        Returns:
> +            Nothing.
> +        '''
> +
> +        # dfu-util fails reads/uploads if the host file already
> exists
> +        if os.path.exists(fn):
> +            os.remove(fn)
> +        run_dfu_util(alt_setting, fn, '-U')
> +
> +    def dfu_write_read_check(size):
> +        '''Test DFU transfers of a specific size of data
> +
> +        This function first writes data to the board then reads it
> back and
> +        compares the written and read back data. Measures are taken
> to avoid
> +        certain types of false positives.
> +
> +        Args:
> +            size: The data size to test.
> +
> +        Returns:
> +            Nothing.
> +        '''
> +
> +        test_f = u_boot_utils.PersistentRandomFile(u_boot_console,
> +            'dfu_%d.bin' % size, size)
> +        readback_fn = u_boot_console.config.result_dir +
> '/dfu_readback.bin' +
> +        u_boot_console.log.action('Writing test data to DFU primary
> ' +
> +            'altsetting')
> +        dfu_write(0, test_f.abs_fn)
> +
> +        u_boot_console.log.action('Writing dummy data to DFU
> secondary ' +
> +            'altsetting to clear DFU buffers')
> +        dfu_write(1, dummy_f.abs_fn)
> +
> +        u_boot_console.log.action('Reading DFU primary altsetting
> for ' +
> +            'comparison')
> +        dfu_read(0, readback_fn)
> +
> +        u_boot_console.log.action('Comparing written and read data')
> +        written_hash = test_f.content_hash
> +        read_back_hash = u_boot_utils.md5sum_file(readback_fn, size)
> +        assert(written_hash == read_back_hash)
> +
> +    # This test may be executed against multiple USB ports. The test
> takes a
> +    # long time, so we don't want to do the whole thing each time.
> Instead,
> +    # execute the full test on the first USB port, and perform a
> very limited
> +    # test on other ports. In the limited case, we solely validate
> that the
> +    # host PC can enumerate the U-Boot USB device.
> +    global first_usb_dev_port
> +    if not first_usb_dev_port:
> +        first_usb_dev_port = env__usb_dev_port
> +    if env__usb_dev_port == first_usb_dev_port:
> +        sizes = test_sizes
> +    else:
> +        sizes = []
> +
> +    dummy_f = u_boot_utils.PersistentRandomFile(u_boot_console,
> +        'dfu_dummy.bin', 1024)
> +
> +    ignore_cleanup_errors = True
> +    try:
> +        start_dfu()
> +
> +        u_boot_console.log.action(
> +            'Overwriting DFU primary altsetting with dummy data')
> +        dfu_write(0, dummy_f.abs_fn)
> +
> +        for size in sizes:
> +            with u_boot_console.log.section("Data size %d" % size):
> +                dfu_write_read_check(size)
> +                # Make the status of each sub-test obvious. If the
> test didn't
> +                # pass, an exception was thrown so this code isn't
> executed.
> +                u_boot_console.log.status_pass('OK')
> +        ignore_cleanup_errors = False
> +    finally:
> +        stop_dfu(ignore_cleanup_errors)

Acked-by: Lukasz Majewski <l.majewski@samsung.com>

Great work Stephen, Thanks !

-- 
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

  reply	other threads:[~2016-01-21 10:50 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-20 22:15 [U-Boot] [PATCH 1/8] test/py: fix timeout to be absolute Stephen Warren
2016-01-20 22:15 ` [U-Boot] [PATCH 2/8] test/py: move U-Boot respawn trigger to the test core Stephen Warren
2016-01-22  3:35   ` Simon Glass
2016-01-20 22:15 ` [U-Boot] [PATCH 3/8] test/py: drain console log at the end of any failed test Stephen Warren
2016-01-22  3:36   ` Simon Glass
2016-01-20 22:15 ` [U-Boot] [PATCH 4/8] test/py: log when tests send CTRL-C Stephen Warren
2016-01-22  3:36   ` Simon Glass
2016-01-20 22:15 ` [U-Boot] [PATCH 5/8] test/py: optionally ignore errors from shell commands Stephen Warren
2016-01-22  3:36   ` Simon Glass
2016-01-20 22:15 ` [U-Boot] [PATCH 6/8] test/py: add various utility code Stephen Warren
2016-01-22  3:36   ` Simon Glass
2016-01-22 16:45     ` Stephen Warren
2016-01-22 16:49     ` Stephen Warren
2016-01-20 22:15 ` [U-Boot] [PATCH 7/8] test/py: ums: add filesystem-based testing Stephen Warren
2016-01-21 11:26   ` Lukasz Majewski
2016-01-22  3:36     ` Simon Glass
2016-01-20 22:15 ` [U-Boot] [PATCH 8/8] test/py: add DFU test Stephen Warren
2016-01-21 10:50   ` Lukasz Majewski [this message]
2016-01-21 18:17     ` Stephen Warren
2016-01-22  3:36       ` Simon Glass
2016-01-21  9:40 ` [U-Boot] [PATCH 1/8] test/py: fix timeout to be absolute Lukasz Majewski
2016-01-22  3:35 ` Simon Glass

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=20160121115000.3782cdb5@amdc2363 \
    --to=l.majewski@samsung.com \
    --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.