[U-Boot] [PATCH v2] travis: Add efi_loader grub2 test

We have all the building blocks now to run arbitrary efi applications in travis. The most important one out there is grub2, so let's add a simple test to verify that grub2 still comes up.
Signed-off-by: Alexander Graf agraf@suse.de
---
This patch depends on the previous travis efi_loader enablement
v1 -> v2:
- Fix syntax errors - Make SMBIOS check conditional (missing cmd on armv7 binary) --- .travis.yml | 8 ++++++ test/py/tests/test_efi_loader.py | 57 +++++++++++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 10 deletions(-)
diff --git a/.travis.yml b/.travis.yml index 1957734..b4ae71a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,9 @@ addons: - gcc-arm-linux-gnueabihf - gcc-aarch64-linux-gnu - iasl + - grub-efi-ia32-bin + - rpm2cpio + - wget
install: # install latest device tree compiler @@ -45,6 +48,9 @@ install: - virtualenv /tmp/venv - . /tmp/venv/bin/activate - pip install pytest + - grub-mkimage -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd + - mkdir ~/grub2-arm + - ( cd ~/grub2-arm; wget -O - http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/s... | rpm2cpio | cpio -di )
env: global: @@ -88,6 +94,8 @@ script: # "-k something" even when $TEST_PY_TEST_SPEC doesnt need a custom # value. - export UBOOT_TRAVIS_BUILD_DIR=`cd .. && pwd`/.bm-work/${TEST_PY_BD}; + cp ~/grub_x86.efi $UBOOT_TRAVIS_BUILD_DIR/; + cp ~/grub2-arm/usr/lib/grub2/arm-efi/grub.efi $UBOOT_TRAVIS_BUILD_DIR/grub_arm.efi; if [[ "${TEST_PY_BD}" != "" ]]; then ./test/py/test.py --bd ${TEST_PY_BD} ${TEST_PY_ID} -k "${TEST_PY_TEST_SPEC:-not a_test_which_does_not_exist}" diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py index 7bf0170..5d7f5db 100644 --- a/test/py/tests/test_efi_loader.py +++ b/test/py/tests/test_efi_loader.py @@ -104,20 +104,18 @@ def test_efi_setup_static(u_boot_console): global net_set_up net_set_up = True
-@pytest.mark.buildconfigspec('cmd_bootefi_hello_compile') -def test_efi_helloworld_net(u_boot_console): - """Run the helloworld.efi binary via TFTP. +def fetch_tftp_file(u_boot_console, env_conf): + """Grab an env described file via TFTP and return its address
- The helloworld.efi file is downloaded from the TFTP server and gets - executed. + A file as described by an env config <env_conf> is downloaded from the TFTP + server. The address to that file is returned. """ - if not net_set_up: pytest.skip('Network not initialized')
- f = u_boot_console.config.env.get('env__efi_loader_helloworld_file', None) + f = u_boot_console.config.env.get(env_conf, None) if not f: - pytest.skip('No hello world binary specified in environment') + pytest.skip('No %s binary specified in environment' % env_conf)
addr = f.get('addr', None) if not addr: @@ -133,14 +131,26 @@ def test_efi_helloworld_net(u_boot_console):
expected_crc = f.get('crc32', None) if not expected_crc: - return + return addr
if u_boot_console.config.buildconfig.get('config_cmd_crc32', 'n') != 'y': - return + return addr
output = u_boot_console.run_command('crc32 %x $filesize' % addr) assert expected_crc in output
+ return addr + +@pytest.mark.buildconfigspec('cmd_bootefi_hello_compile') +def test_efi_helloworld_net(u_boot_console): + """Run the helloworld.efi binary via TFTP. + + The helloworld.efi file is downloaded from the TFTP server and gets + executed. + """ + + addr = fetch_tftp_file(u_boot_console, 'env__efi_loader_helloworld_file') + output = u_boot_console.run_command('bootefi %x' % addr) expected_text = 'Hello, world' assert expected_text in output @@ -156,3 +166,30 @@ def test_efi_helloworld_builtin(u_boot_console): output = u_boot_console.run_command('bootefi hello') expected_text = 'Hello, world' assert expected_text in output + +@pytest.mark.buildconfigspec('cmd_bootefi') +def test_efi_grub_net(u_boot_console): + """Run the grub.efi binary via TFTP. + + The grub.efi file is downloaded from the TFTP server and gets + executed. + """ + + addr = fetch_tftp_file(u_boot_console, 'env__efi_loader_grub_file') + + u_boot_console.run_command('bootefi %x' % addr, wait_for_prompt=False) + + # Verify that we have an SMBIOS table + check_smbios = u_boot_console.config.env.get('env__efi_loader_check_smbios', False) + if check_smbios: + u_boot_console.wait_for('grub>') + output = u_boot_console.run_command('lsefisystab', wait_for_prompt=False, wait_for_echo=False) + u_boot_console.wait_for('SMBIOS') + + # Then exit cleanly + u_boot_console.wait_for('grub>') + output = u_boot_console.run_command('exit', wait_for_prompt=False, wait_for_echo=False) + u_boot_console.wait_for('r = 0') + + # And give us our U-Boot prompt back + u_boot_console.run_command('')

On 11/18/2016 05:18 AM, Alexander Graf wrote:
We have all the building blocks now to run arbitrary efi applications in travis. The most important one out there is grub2, so let's add a simple test to verify that grub2 still comes up.
diff --git a/.travis.yml b/.travis.yml
@@ -45,6 +48,9 @@ install:
- virtualenv /tmp/venv
- . /tmp/venv/bin/activate
- pip install pytest
- grub-mkimage -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
- mkdir ~/grub2-arm
- ( cd ~/grub2-arm; wget -O - http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/s... | rpm2cpio | cpio -di )
Do we really want to do this for all the build-only jobs too? I might have expected to do this inside the test scripts that actually use those binaries.
diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py
+@pytest.mark.buildconfigspec('cmd_bootefi')
- u_boot_console.run_command('bootefi %x' % addr, wait_for_prompt=False)
- # Verify that we have an SMBIOS table
- check_smbios = u_boot_console.config.env.get('env__efi_loader_check_smbios', False)
- if check_smbios:
u_boot_console.wait_for('grub>')
output = u_boot_console.run_command('lsefisystab', wait_for_prompt=False, wait_for_echo=False)
u_boot_console.wait_for('SMBIOS')
- # Then exit cleanly
- u_boot_console.wait_for('grub>')
- output = u_boot_console.run_command('exit', wait_for_prompt=False, wait_for_echo=False)
- u_boot_console.wait_for('r = 0')
- # And give us our U-Boot prompt back
- u_boot_console.run_command('')
I can't help wondering if adding push_prompt() function (for use in a Python "with" statement) to u_boot_console wouldn't be better; that would avoid all the wait_for_prompt=False and wait_for(prompt) logic there.

On Mon, Nov 21, 2016 at 03:21:43PM -0700, Stephen Warren wrote:
On 11/18/2016 05:18 AM, Alexander Graf wrote:
We have all the building blocks now to run arbitrary efi applications in travis. The most important one out there is grub2, so let's add a simple test to verify that grub2 still comes up.
diff --git a/.travis.yml b/.travis.yml
@@ -45,6 +48,9 @@ install:
- virtualenv /tmp/venv
- . /tmp/venv/bin/activate
- pip install pytest
- grub-mkimage -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
- mkdir ~/grub2-arm
- ( cd ~/grub2-arm; wget -O - http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/s... | rpm2cpio | cpio -di )
Do we really want to do this for all the build-only jobs too? I might have expected to do this inside the test scripts that actually use those binaries.
So, it's the difference between making various jobs / stanzas more correct vs taking more time to do stuff. Unless this starts to push the "catch-all" arm job over the time limit, I don't think it's a big deal either way. And since travis-ci will tell us how long a given stanza takes we'll have a good idea pretty quick on if that's starting to take too long. That said, I don't have a strong opinion here and it wouldn't be too hard to move all of this into being under the TEST_PY_BD check and since we aren't relying on apt, it's not going to be time-in-apt factor.

On 21/11/2016 23:31, Tom Rini wrote:
On Mon, Nov 21, 2016 at 03:21:43PM -0700, Stephen Warren wrote:
On 11/18/2016 05:18 AM, Alexander Graf wrote:
We have all the building blocks now to run arbitrary efi applications in travis. The most important one out there is grub2, so let's add a simple test to verify that grub2 still comes up.
diff --git a/.travis.yml b/.travis.yml
@@ -45,6 +48,9 @@ install:
- virtualenv /tmp/venv
- . /tmp/venv/bin/activate
- pip install pytest
- grub-mkimage -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
- mkdir ~/grub2-arm
- ( cd ~/grub2-arm; wget -O - http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/s... | rpm2cpio | cpio -di )
Do we really want to do this for all the build-only jobs too? I might have expected to do this inside the test scripts that actually use those binaries.
So, it's the difference between making various jobs / stanzas more correct vs taking more time to do stuff. Unless this starts to push the "catch-all" arm job over the time limit, I don't think it's a big deal either way. And since travis-ci will tell us how long a given stanza takes we'll have a good idea pretty quick on if that's starting to take too long. That said, I don't have a strong opinion here and it wouldn't be too hard to move all of this into being under the TEST_PY_BD check and since we aren't relying on apt, it's not going to be time-in-apt factor.
If we move it into TEST_PY_BD, we would either run the same sequence over and over again for individual tests or check if the file exists inside the generation path. Either way, it will get less readable :).
Overall, we're talking of 1s of build time for this:
https://travis-ci.org/agraf/u-boot/jobs/177000864
so I'd definitely prefer to keep it simple rather than optimized.
Alex

On 11/21/2016 04:15 PM, Alexander Graf wrote:
On 21/11/2016 23:31, Tom Rini wrote:
On Mon, Nov 21, 2016 at 03:21:43PM -0700, Stephen Warren wrote:
On 11/18/2016 05:18 AM, Alexander Graf wrote:
We have all the building blocks now to run arbitrary efi applications in travis. The most important one out there is grub2, so let's add a simple test to verify that grub2 still comes up.
diff --git a/.travis.yml b/.travis.yml
@@ -45,6 +48,9 @@ install:
- virtualenv /tmp/venv
- . /tmp/venv/bin/activate
- pip install pytest
- grub-mkimage -o ~/grub_x86.efi -O i386-efi normal echo
lsefimmap lsefi lsefisystab efinet tftp minicmd
- mkdir ~/grub2-arm
- ( cd ~/grub2-arm; wget -O -
http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/s... | rpm2cpio | cpio -di )
Do we really want to do this for all the build-only jobs too? I might have expected to do this inside the test scripts that actually use those binaries.
So, it's the difference between making various jobs / stanzas more correct vs taking more time to do stuff. Unless this starts to push the "catch-all" arm job over the time limit, I don't think it's a big deal either way. And since travis-ci will tell us how long a given stanza takes we'll have a good idea pretty quick on if that's starting to take too long. That said, I don't have a strong opinion here and it wouldn't be too hard to move all of this into being under the TEST_PY_BD check and since we aren't relying on apt, it's not going to be time-in-apt factor.
If we move it into TEST_PY_BD, we would either run the same sequence over and over again for individual tests or check if the file exists inside the generation path. Either way, it will get less readable :).
I believe each test job configures a new container, so no, the change I suggested would mean a given job would either:
a) Run a build without downloading the test EFI RPM.
b) Run a test and download the EFI RPM once.
It seems trivial to just put this in the right place, although admittedly if it's quick it's not going to save much, except that it will make all the compile-only tests not depend on so many potentially-intermittent network accesses.
Overall, we're talking of 1s of build time for this:
https://travis-ci.org/agraf/u-boot/jobs/177000864
so I'd definitely prefer to keep it simple rather than optimized.

On 21/11/2016 23:21, Stephen Warren wrote:
On 11/18/2016 05:18 AM, Alexander Graf wrote:
We have all the building blocks now to run arbitrary efi applications in travis. The most important one out there is grub2, so let's add a simple test to verify that grub2 still comes up.
diff --git a/.travis.yml b/.travis.yml
@@ -45,6 +48,9 @@ install:
- virtualenv /tmp/venv
- . /tmp/venv/bin/activate
- pip install pytest
- grub-mkimage -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap
lsefi lsefisystab efinet tftp minicmd
- mkdir ~/grub2-arm
- ( cd ~/grub2-arm; wget -O -
http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/s... | rpm2cpio | cpio -di )
Do we really want to do this for all the build-only jobs too? I might have expected to do this inside the test scripts that actually use those binaries.
diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py
+@pytest.mark.buildconfigspec('cmd_bootefi')
- u_boot_console.run_command('bootefi %x' % addr,
wait_for_prompt=False)
- # Verify that we have an SMBIOS table
- check_smbios =
u_boot_console.config.env.get('env__efi_loader_check_smbios', False)
- if check_smbios:
u_boot_console.wait_for('grub>')
output = u_boot_console.run_command('lsefisystab',
wait_for_prompt=False, wait_for_echo=False)
u_boot_console.wait_for('SMBIOS')
- # Then exit cleanly
- u_boot_console.wait_for('grub>')
- output = u_boot_console.run_command('exit',
wait_for_prompt=False, wait_for_echo=False)
- u_boot_console.wait_for('r = 0')
- # And give us our U-Boot prompt back
- u_boot_console.run_command('')
I can't help wondering if adding push_prompt() function (for use in a Python "with" statement) to u_boot_console wouldn't be better; that would avoid all the wait_for_prompt=False and wait_for(prompt) logic there.
What would that function do? The same?
JFYI, I've added the html log output for the sequence above at the end of the email.
Alex
tftpboot 80400000 grub_arm.efi smc911x: MAC 52:54:00:12:34:56 smc911x: detected LAN9118 controller smc911x: phy initialized smc911x: MAC 52:54:00:12:34:56 Using smc911x-0 device TFTP from server 10.0.2.2; our IP address is 10.0.2.15 Filename 'grub_arm.efi'. Load address: 0x80400000 Loading: *%08################################################################# ################################################################# ############## 14.3 MiB/s done Bytes transferred = 732672 (b2e00 hex) smc911x: MAC 52:54:00:12:34:56 => crc32 80400000 $filesize CRC32 for 80400000 ... 804b2dff ==> 4afa7ec6 => bootefi 80400000 ## Starting EFI application at 80400000 ... WARNING: Invalid device tree, expect boot to fail Scanning disks on mmc... Card did not respond to voltage select! MMC Device 1 not found MMC Device 2 not found MMC Device 3 not found Found 0 disks %1b[?25hWelcome to GRUB!
smc911x: detected LAN9118 controller smc911x: phy initialized smc911x: MAC 52:54:00:12:34:56 smc911x: detected LAN9118 controller smc911x: phy initialized smc911x: MAC 52:54:00:12:34:56 %1b[2J%1b[18t%1b[1;26fGNU GRUB version 2.02~beta2
%1b[?25h Minimal BASH-like line editing is supported. For the first word, TAB lists possible command completions. Anywhere else TAB lists possible device or file completions.
grub> %1b[9;6fe%1b[9;7f%1b[9;7fx%1b[9;8f%1b[9;8fi%1b[9;9f%1b[9;9ft%1b[9;10f ## Application terminated, r = 0

On 11/21/2016 04:21 PM, Alexander Graf wrote:
On 21/11/2016 23:21, Stephen Warren wrote:
On 11/18/2016 05:18 AM, Alexander Graf wrote:
We have all the building blocks now to run arbitrary efi applications in travis. The most important one out there is grub2, so let's add a simple test to verify that grub2 still comes up.
diff --git a/.travis.yml b/.travis.yml
@@ -45,6 +48,9 @@ install:
- virtualenv /tmp/venv
- . /tmp/venv/bin/activate
- pip install pytest
- grub-mkimage -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap
lsefi lsefisystab efinet tftp minicmd
- mkdir ~/grub2-arm
- ( cd ~/grub2-arm; wget -O -
http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/s...
| rpm2cpio | cpio -di )
Do we really want to do this for all the build-only jobs too? I might have expected to do this inside the test scripts that actually use those binaries.
diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py
+@pytest.mark.buildconfigspec('cmd_bootefi')
- u_boot_console.run_command('bootefi %x' % addr,
wait_for_prompt=False)
- # Verify that we have an SMBIOS table
- check_smbios =
u_boot_console.config.env.get('env__efi_loader_check_smbios', False)
- if check_smbios:
u_boot_console.wait_for('grub>')
output = u_boot_console.run_command('lsefisystab',
wait_for_prompt=False, wait_for_echo=False)
u_boot_console.wait_for('SMBIOS')
- # Then exit cleanly
- u_boot_console.wait_for('grub>')
- output = u_boot_console.run_command('exit',
wait_for_prompt=False, wait_for_echo=False)
- u_boot_console.wait_for('r = 0')
- # And give us our U-Boot prompt back
- u_boot_console.run_command('')
I can't help wondering if adding push_prompt() function (for use in a Python "with" statement) to u_boot_console wouldn't be better; that would avoid all the wait_for_prompt=False and wait_for(prompt) logic there.
What would that function do? The same?
The internal implementation would likely look the same, but it would avoid needing to implement/replicate such low-level prompt-parsing details in each test that invokes "sub-commands" with different prompts.

On Fri, Nov 18, 2016 at 01:18:00PM +0100, Alexander Graf wrote:
We have all the building blocks now to run arbitrary efi applications in travis. The most important one out there is grub2, so let's add a simple test to verify that grub2 still comes up.
Signed-off-by: Alexander Graf agraf@suse.de
Applied to u-boot/master, thanks!
participants (3)
-
Alexander Graf
-
Stephen Warren
-
Tom Rini