[U-Boot] [PATCH v3 1/1] test/py: provide example scripts for integrating qemu
Heinrich Schuchardt
xypron.glpk at gmx.de
Wed Sep 20 17:43:52 UTC 2017
On 09/20/2017 06:41 PM, Stephen Warren wrote:
> On 09/19/2017 02:04 PM, Heinrich Schuchardt wrote:
>> The necessary parameters for running Python tests on qemu are
>> tedious to find.
>>
>> The patch adds a complete example for running the Python tests for
>> qemu-x86_defconfig on an X86 system.
>
>> diff --git a/test/py/README.md b/test/py/README.md
>
>> +#### Running tests for qemu-x86\_defconfig on an x86 system
>> +
>> +We build u-boot.rom with
>> +
>> + export BUILD_ROM=y
>> + make mrproper
>> + make qemu-x86_defconfig
>> + make
>
> Nit: I'd rather write that as:
>
> BUILD_ROM=y make
>
> That way, we don't have to set BUILD_ROM permanently in the current
> shell's environment, so it won't affect anything else that's done later
> in the shell.
>
> To avoid polluting the source tree with build results, why not build
> with O=./build-qemu-x86, and use that as the --build-dir argument to
> test/py?
Building in the source tree is the default for U-Boot.
Why should we make the example more complicated?
>
>> +We create directories `$HOME/ubtest/bin` and `$HOME/ubtest/py` for
>> the script
>> +files below and `../tftp` for the tftp server.
>
> Why not $HOME/ubtest/tftp? The meaning of "../tftp" can change depending
> on current directory.
I can give it a try.
>
>> +File `u-boot-test-console` chmod 755
>> +
>> + #!/bin/sh
>> + touch /tmp/u-boot-monitor-socket
>
> This creates a regular file not a socket. I believe you can remove this
> command.
>
> Ah, there's a race condition here. By the time u-boot-test-reset is run
> the first time, qemu typically hasn't run far enough to create
> /tmp/u-boot-monitor-socket, and so u-boot-test-reset fails to open it.
> If I fix that by making u-boot-test-reset wait until the control socket
> actually does exist, then test/py fails because it sees two signon
> messages from U-Boot and thinks it crashed; one from when qemu started
> and booted U-Boot, and one because the first invocation of
> u-boot-test-reset resets the system which causes another signon to
> appear. Perhaps this is why Tom Rini's test/py+qemu integration spawns a
> new instance of qemu every time u-boot-test-console is run, and make
> u-boot-test-reset a no-op.
>
> To solve this, I was going to say:
>
> a) Add -S to the qemu command. This causes qemu to perform all
> initialization (e.g. creating/opening the monitor socket) but doesn't
> actually allow the target to run. This prevents the undesired immediate
> boot of the system.
>
> b) Add the following to the top of u-boot-test-reset so that it waits
> for the monitor socket to exist before attempting to use it:
>
> for i in $(seq 50); do
> if [ -f /tmp/u-boot-monitor-socket ]; then
> break
> fi
> sleep 0.1
> done
Why make the example more complicated?
>
> c) Make u-boot-test-reset send U-Boot command "c" to start U-Boot
> executing instead of or in additionk to "system_reset" to cause a reset.
>
> However, none of that is necessary.
Some test scripts explicitly reset U-Boot:
test/py/tests/test_fit.py:362: cons.restart_uboot()
test/py/tests/test_fit.py:387: cons.restart_uboot()
test/py/tests/test_fit.py:399: cons.restart_uboot()
test/py/tests/test_fit.py:411: cons.restart_uboot()
test/py/tests/test_fit.py:428: cons.restart_uboot()
test/py/tests/test_vboot.py:70: cons.restart_uboot()
test/py/tests/test_vboot.py:198: cons.restart_uboot()
test/py/tests/test_efi_selftest.py:25: u_boot_console.restart_uboot();
> u-boot-test-console is re-executed
> every time test/py wants to connect to the target, which happens (a)
> when test/py starts the first test, and (b) any time a test fails, and
> test/py wants to clear all state and reconnect to the target (e.g. the
> console command might have failed rather than the target, so the console
> command is restarted too). As such, there's no need to implement
> u-boot-test-reset at all with qemu; just make it a complete no-op. That
> way, you also don't need qemu's -monitor at all.
>
>> + exec qemu-system-x86_64 -bios u-boot.rom -nographic -netdev \
>> +
>> user,id=eth0,tftp=../tftp,net=192.168.76.0/24,dhcpstart=192.168.76.9 \
>> + -device e1000,netdev=eth0 -machine pc-i440fx-2.8 \
>
> Is machine version 2.8 strictly necessary? The qemu packaged in Ubuntu
> 14.04 doesn't support that version, which restricts the usefulness of
> the example. Can version 2.0 work for example? It seems to work fine for
> me. My qemu supports the following i440fx:
It is time to upgrade your Linux distribution ;)
I can change that to pc-i440fx-2.0.
>
> qemu-system-x86_64 -machine help | grep i440fx
> pc-i440fx-2.0 Standard PC (i440FX + PIIX, 1996)
> pc-i440fx-1.4 Standard PC (i440FX + PIIX, 1996)
> pc-i440fx-1.5 Standard PC (i440FX + PIIX, 1996)
> pc Ubuntu 14.04 PC (i440FX + PIIX, 1996) (alias of
> pc-i440fx-trusty)
> pc-i440fx-trusty Ubuntu 14.04 PC (i440FX + PIIX, 1996) (default)
> pc-i440fx-1.7 Standard PC (i440FX + PIIX, 1996)
> pc-i440fx-1.5-saucy Standard PC (i440FX + PIIX, 1996) (alias of
> pc-i440fx-1.5-qemu-kvm)
> pc-i440fx-1.5-qemu-kvm Standard PC (i440FX + PIIX, 1996)
> pc-i440fx-1.6 Standard PC (i440FX + PIIX, 1996)
>
>> +File `u-boot-test-quit` chmod 755
>> +
>> + #!/bin/sh
>> + echo quit | socat - UNIX-CONNECT:/tmp/u-boot-monitor-socket
>> +
>> +This script is called when all tests are completed. The `quit`
>> command is
>> +passed to the qemu control console to terminate the qemu session.
>
> test/py doesn't run u-boot-test-quit. Do you have a local change that
> makes it do that? My knee-jerk reaction is that it's OK to enhance
> test/py to run such a script, but let's not document it in the example
> until it does. That said, I'd assume qemu should exit as soon as test/py
> exits since stdin will go away, so this shouldn't actually be needed in
> this case.
>
I will remove u-boot-test-quit.
>> +File `u-boot-test-reset` chmod 755
>> +
>> + #!/bin/sh
>> + echo system_reset | socat - UNIX-CONNECT:/tmp/u-boot-monitor-socket
>> + true
>
> As mentioned previously, the true doesn't appear to be required, and
> hides legitimate errors.
Without true all tests fail on my machine (Debian Stretch) which uses
dash to implement /bin/sh. So we should keep it. It does no harm.
>
>> +In the `$HOME/ubtest/py` directory we create file
>> `u_boot_boardenv_qemu_x86.py`
>
> Since the file mode is mentioned for all the other files, let's mention
> it here too.
644
>
>> + env__net_dhcp_server = True
>> + env__efi_loader_helloworld_file = {
>> + "fn": "helloworld.efi",
>> + "size": 4298,
>> + "crc32": "55d96ef8",
>> + }
>> +
>> +The parameter `env__net_dhcp_server` enables the network tests. The
>> parameter
>> +`env__efi_loader_helloworld_file` is needed to make the file
>> `helloworld.efi`
>> +available which is loaded from the tftp server in `test_efi_loader.py`.
>> +
>> +The fields size and crc32 have to be updated to match the actual
>> values. The
>> +`crc32` command can be used to determine the latter.
>
> Why not have Python determine those values automatically? Here's a
> snippet from my uboot-test-hooks repo that does that. Since people will
> simply be copy-and-pasting the example, it shouldn't matter that it's
> non-trivial:
>
> {
> "fn": file_name,
> "size": os.path.getsize(file_full),
> "crc32": hex(binascii.crc32(open(file_full, 'rb').read()) & \
> 0xffffffff)[2:],
> }
What does file_full refer to? I cannot find this string in U-Boot.
Are the necessary packages imported when the python script is included?
I doubt it. There is no string binascii in U-Boot.
We cannot hard code the full path to helloworld.efi here because the
value of $HOME_PATH is not known.
I would prefer to keep the example simple.
>
>> +We now can run the Python tests with
>> +
>> + export PATH=$HOME/ubtest/bin:/usr/bin:/bin
>
> Let's not hard-code /usr/bin:/bin; some people may rely on binaries
> elsewhere. Also I know that the recently added gpt tests rely on sgdisk
> which is in sbin on my system at least. Also quote to avoid issues with
> spaces in path names. How about:
>
> PATH="$HOME/ubtest/bin:$PATH"
I can change it.
>
>> + export PYTHONPATH=$HOME/ubtest/py
>
> People might have PYTHONPATH set already (e.g. if using a virtualenv or
> having installed some packages in their home directory). How about:
>
> PYTHONPATH="$HOME/ubtest/py:$PYTHONPATH"
>
Together with your suggestion below this is fine.
>> + ./test/py/test.py --bd=qemu-x86 --build-dir=.
>
> As above, I'd suggest setting environment variables just for the one
> command rather than permanently changing them:
>
> PATH="$HOME/ubtest/bin:$PATH" \
> PYTHONPATH="$HOME/ubtest/py:$PYTHONPATH" \
> ./test/py/test.py --bd=qemu-x86 --build-dir=./build-qemu-x86
>
That makes sense.
Thank you for reviewing.
Best regards
Heinrich
More information about the U-Boot
mailing list