From 752c3769874596d012cd8325099d2ae20123f989 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 9 Feb 2025 09:07:14 -0700 Subject: test/py: Shorten u_boot_console This fixture name is quite long and results in lots of verbose code. We know this is U-Boot so the 'u_boot_' part is not necessary. But it is also a bit of a misnomer, since it provides access to all the information available to tests. It is not just the console. It would be too confusing to use con as it would be confused with config and it is probably too short. So shorten it to 'ubman'. Signed-off-by: Simon Glass Link: https://lore.kernel.org/u-boot/CAFLszTgPa4aT_J9h9pqeTtLCVn4x2JvLWRcWRD8NaN3uoSAtyA@mail.gmail.com/ --- test/py/tests/test_android/test_ab.py | 46 +++++++-------- test/py/tests/test_android/test_abootimg.py | 90 ++++++++++++++--------------- test/py/tests/test_android/test_avb.py | 48 +++++++-------- 3 files changed, 92 insertions(+), 92 deletions(-) (limited to 'test/py/tests/test_android') diff --git a/test/py/tests/test_android/test_ab.py b/test/py/tests/test_android/test_ab.py index 9bf1a0eb00a..739b7ce695d 100644 --- a/test/py/tests/test_android/test_ab.py +++ b/test/py/tests/test_android/test_ab.py @@ -10,11 +10,11 @@ import u_boot_utils class ABTestDiskImage(object): """Disk Image used by the A/B tests.""" - def __init__(self, u_boot_console): + def __init__(self, ubman): """Initialize a new ABTestDiskImage object. Args: - u_boot_console: A U-Boot console. + ubman: A U-Boot console. Returns: Nothing. @@ -22,40 +22,40 @@ class ABTestDiskImage(object): filename = 'test_ab_disk_image.bin' - persistent = u_boot_console.config.persistent_data_dir + '/' + filename - self.path = u_boot_console.config.result_dir + '/' + filename + persistent = ubman.config.persistent_data_dir + '/' + filename + self.path = ubman.config.result_dir + '/' + filename - with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent): + with u_boot_utils.persistent_file_helper(ubman.log, persistent): if os.path.exists(persistent): - u_boot_console.log.action('Disk image file ' + persistent + + ubman.log.action('Disk image file ' + persistent + ' already exists') else: - u_boot_console.log.action('Generating ' + persistent) + ubman.log.action('Generating ' + persistent) fd = os.open(persistent, os.O_RDWR | os.O_CREAT) os.ftruncate(fd, 524288) os.close(fd) cmd = ('sgdisk', persistent) - u_boot_utils.run_and_log(u_boot_console, cmd) + u_boot_utils.run_and_log(ubman, cmd) cmd = ('sgdisk', '--new=1:64:512', '--change-name=1:misc', persistent) - u_boot_utils.run_and_log(u_boot_console, cmd) + u_boot_utils.run_and_log(ubman, cmd) cmd = ('sgdisk', '--load-backup=' + persistent) - u_boot_utils.run_and_log(u_boot_console, cmd) + u_boot_utils.run_and_log(ubman, cmd) cmd = ('cp', persistent, self.path) - u_boot_utils.run_and_log(u_boot_console, cmd) + u_boot_utils.run_and_log(ubman, cmd) di = None @pytest.fixture(scope='function') -def ab_disk_image(u_boot_console): +def ab_disk_image(ubman): global di if not di: - di = ABTestDiskImage(u_boot_console) + di = ABTestDiskImage(ubman) return di -def ab_dump(u_boot_console, slot_num, crc): - output = u_boot_console.run_command('bcb ab_dump host 0#misc') +def ab_dump(ubman, slot_num, crc): + output = ubman.run_command('bcb ab_dump host 0#misc') header, slot0, slot1 = output.split('\r\r\n\r\r\n') slots = [slot0, slot1] slot_suffixes = ['_a', '_b'] @@ -79,20 +79,20 @@ def ab_dump(u_boot_console, slot_num, crc): @pytest.mark.buildconfigspec('android_ab') @pytest.mark.buildconfigspec('cmd_bcb') @pytest.mark.requiredtool('sgdisk') -def test_ab(ab_disk_image, u_boot_console): +def test_ab(ab_disk_image, ubman): """Test the 'bcb ab_select' command.""" - u_boot_console.run_command('host bind 0 ' + ab_disk_image.path) + ubman.run_command('host bind 0 ' + ab_disk_image.path) - output = u_boot_console.run_command('bcb ab_select slot_name host 0#misc') + output = ubman.run_command('bcb ab_select slot_name host 0#misc') assert 're-initializing A/B metadata' in output assert 'Attempting slot a, tries remaining 7' in output - output = u_boot_console.run_command('printenv slot_name') + output = ubman.run_command('printenv slot_name') assert 'slot_name=a' in output - ab_dump(u_boot_console, 0, '0xd438d1b9') + ab_dump(ubman, 0, '0xd438d1b9') - output = u_boot_console.run_command('bcb ab_select slot_name host 0:1') + output = ubman.run_command('bcb ab_select slot_name host 0:1') assert 'Attempting slot b, tries remaining 7' in output - output = u_boot_console.run_command('printenv slot_name') + output = ubman.run_command('printenv slot_name') assert 'slot_name=b' in output - ab_dump(u_boot_console, 1, '0x011ec016') + ab_dump(ubman, 1, '0x011ec016') diff --git a/test/py/tests/test_android/test_abootimg.py b/test/py/tests/test_android/test_abootimg.py index 6a8ff34538b..fd3e08fa899 100644 --- a/test/py/tests/test_android/test_abootimg.py +++ b/test/py/tests/test_android/test_abootimg.py @@ -105,78 +105,78 @@ dtb2_addr = vloadaddr + dtb2_offset class AbootimgTestDiskImage(object): """Disk image used by abootimg tests.""" - def __init__(self, u_boot_console, image_name, hex_img): + def __init__(self, ubman, image_name, hex_img): """Initialize a new AbootimgDiskImage object. Args: - u_boot_console: A U-Boot console. + ubman: A U-Boot console. Returns: Nothing. """ - gz_hex = u_boot_console.config.persistent_data_dir + '/' + image_name + '.gz.hex' - gz = u_boot_console.config.persistent_data_dir + '/' + image_name + '.gz' + gz_hex = ubman.config.persistent_data_dir + '/' + image_name + '.gz.hex' + gz = ubman.config.persistent_data_dir + '/' + image_name + '.gz' filename = image_name - persistent = u_boot_console.config.persistent_data_dir + '/' + filename - self.path = u_boot_console.config.result_dir + '/' + filename - u_boot_console.log.action('persistent is ' + persistent) - with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent): + persistent = ubman.config.persistent_data_dir + '/' + filename + self.path = ubman.config.result_dir + '/' + filename + ubman.log.action('persistent is ' + persistent) + with u_boot_utils.persistent_file_helper(ubman.log, persistent): if os.path.exists(persistent): - u_boot_console.log.action('Disk image file ' + persistent + + ubman.log.action('Disk image file ' + persistent + ' already exists') else: - u_boot_console.log.action('Generating ' + persistent) + ubman.log.action('Generating ' + persistent) f = open(gz_hex, "w") f.write(hex_img) f.close() cmd = ('xxd', '-r', '-p', gz_hex, gz) - u_boot_utils.run_and_log(u_boot_console, cmd) + u_boot_utils.run_and_log(ubman, cmd) cmd = ('gunzip', '-9', gz) - u_boot_utils.run_and_log(u_boot_console, cmd) + u_boot_utils.run_and_log(ubman, cmd) cmd = ('cp', persistent, self.path) - u_boot_utils.run_and_log(u_boot_console, cmd) + u_boot_utils.run_and_log(ubman, cmd) gtdi1 = None @pytest.fixture(scope='function') -def abootimg_disk_image(u_boot_console): +def abootimg_disk_image(ubman): """pytest fixture to provide a AbootimgTestDiskImage object to tests. - This is function-scoped because it uses u_boot_console, which is also + This is function-scoped because it uses ubman, which is also function-scoped. However, we don't need to actually do any function-scope work, so this simply returns the same object over and over each time.""" global gtdi1 if not gtdi1: - gtdi1 = AbootimgTestDiskImage(u_boot_console, 'boot.img', img_hex) + gtdi1 = AbootimgTestDiskImage(ubman, 'boot.img', img_hex) return gtdi1 gtdi2 = None @pytest.fixture(scope='function') -def abootimgv4_disk_image_vboot(u_boot_console): +def abootimgv4_disk_image_vboot(ubman): """pytest fixture to provide a AbootimgTestDiskImage object to tests. - This is function-scoped because it uses u_boot_console, which is also + This is function-scoped because it uses ubman, which is also function-scoped. However, we don't need to actually do any function-scope work, so this simply returns the same object over and over each time.""" global gtdi2 if not gtdi2: - gtdi2 = AbootimgTestDiskImage(u_boot_console, 'vendor_boot.img', vboot_img_hex) + gtdi2 = AbootimgTestDiskImage(ubman, 'vendor_boot.img', vboot_img_hex) return gtdi2 gtdi3 = None @pytest.fixture(scope='function') -def abootimgv4_disk_image_boot(u_boot_console): +def abootimgv4_disk_image_boot(ubman): """pytest fixture to provide a AbootimgTestDiskImage object to tests. - This is function-scoped because it uses u_boot_console, which is also + This is function-scoped because it uses ubman, which is also function-scoped. However, we don't need to actually do any function-scope work, so this simply returns the same object over and over each time.""" global gtdi3 if not gtdi3: - gtdi3 = AbootimgTestDiskImage(u_boot_console, 'bootv4.img', boot_img_hex) + gtdi3 = AbootimgTestDiskImage(ubman, 'bootv4.img', boot_img_hex) return gtdi3 @pytest.mark.boardspec('sandbox') @@ -185,42 +185,42 @@ def abootimgv4_disk_image_boot(u_boot_console): @pytest.mark.buildconfigspec('cmd_fdt') @pytest.mark.requiredtool('xxd') @pytest.mark.requiredtool('gunzip') -def test_abootimg(abootimg_disk_image, u_boot_console): +def test_abootimg(abootimg_disk_image, ubman): """Test the 'abootimg' command.""" - u_boot_console.log.action('Loading disk image to RAM...') - u_boot_console.run_command('setenv loadaddr 0x%x' % (loadaddr)) - u_boot_console.run_command('host load hostfs - 0x%x %s' % (loadaddr, + ubman.log.action('Loading disk image to RAM...') + ubman.run_command('setenv loadaddr 0x%x' % (loadaddr)) + ubman.run_command('host load hostfs - 0x%x %s' % (loadaddr, abootimg_disk_image.path)) - u_boot_console.log.action('Testing \'abootimg get ver\'...') - response = u_boot_console.run_command('abootimg get ver') + ubman.log.action('Testing \'abootimg get ver\'...') + response = ubman.run_command('abootimg get ver') assert response == "2" - u_boot_console.run_command('abootimg get ver v') - response = u_boot_console.run_command('env print v') + ubman.run_command('abootimg get ver v') + response = ubman.run_command('env print v') assert response == 'v=2' - u_boot_console.log.action('Testing \'abootimg get recovery_dtbo\'...') - response = u_boot_console.run_command('abootimg get recovery_dtbo a') + ubman.log.action('Testing \'abootimg get recovery_dtbo\'...') + response = ubman.run_command('abootimg get recovery_dtbo a') assert response == 'Error: recovery_dtbo_size is 0' - u_boot_console.log.action('Testing \'abootimg dump dtb\'...') - response = u_boot_console.run_command('abootimg dump dtb').replace('\r', '') + ubman.log.action('Testing \'abootimg dump dtb\'...') + response = ubman.run_command('abootimg dump dtb').replace('\r', '') assert response == dtb_dump_resp - u_boot_console.log.action('Testing \'abootimg get dtb_load_addr\'...') - u_boot_console.run_command('abootimg get dtb_load_addr a') - response = u_boot_console.run_command('env print a') + ubman.log.action('Testing \'abootimg get dtb_load_addr\'...') + ubman.run_command('abootimg get dtb_load_addr a') + response = ubman.run_command('env print a') assert response == 'a=11f00000' - u_boot_console.log.action('Testing \'abootimg get dtb --index\'...') - u_boot_console.run_command('abootimg get dtb --index=1 dtb1_start') - response = u_boot_console.run_command('env print dtb1_start') + ubman.log.action('Testing \'abootimg get dtb --index\'...') + ubman.run_command('abootimg get dtb --index=1 dtb1_start') + response = ubman.run_command('env print dtb1_start') correct_str = "dtb1_start=%x" % (dtb1_addr) assert response == correct_str - u_boot_console.run_command('fdt addr $dtb1_start') - u_boot_console.run_command('fdt get value v / model') - response = u_boot_console.run_command('env print v') + ubman.run_command('fdt addr $dtb1_start') + ubman.run_command('fdt get value v / model') + response = ubman.run_command('env print v') assert response == 'v=x2' @pytest.mark.boardspec('sandbox') @@ -229,10 +229,10 @@ def test_abootimg(abootimg_disk_image, u_boot_console): @pytest.mark.buildconfigspec('cmd_fdt') @pytest.mark.requiredtool('xxd') @pytest.mark.requiredtool('gunzip') -def test_abootimgv4(abootimgv4_disk_image_vboot, abootimgv4_disk_image_boot, u_boot_console): +def test_abootimgv4(abootimgv4_disk_image_vboot, abootimgv4_disk_image_boot, ubman): """Test the 'abootimg' command with boot image header v4.""" - cons = u_boot_console + cons = ubman cons.log.action('Loading disk image to RAM...') cons.run_command('setenv loadaddr 0x%x' % (loadaddr)) cons.run_command('setenv vloadaddr 0x%x' % (vloadaddr)) diff --git a/test/py/tests/test_android/test_avb.py b/test/py/tests/test_android/test_avb.py index 865efbca4de..451a476da76 100644 --- a/test/py/tests/test_android/test_avb.py +++ b/test/py/tests/test_android/test_avb.py @@ -24,34 +24,34 @@ temp_addr2 = 0x90002000 @pytest.mark.buildconfigspec('cmd_avb') @pytest.mark.buildconfigspec('cmd_mmc') -def test_avb_verify(u_boot_console): +def test_avb_verify(ubman): """Run AVB 2.0 boot verification chain with avb subset of commands """ success_str = "Verification passed successfully" - response = u_boot_console.run_command('avb init %s' %str(mmc_dev)) + response = ubman.run_command('avb init %s' %str(mmc_dev)) assert response == '' - response = u_boot_console.run_command('avb verify') + response = ubman.run_command('avb verify') assert response.find(success_str) @pytest.mark.buildconfigspec('cmd_avb') @pytest.mark.buildconfigspec('cmd_mmc') @pytest.mark.notbuildconfigspec('sandbox') -def test_avb_mmc_uuid(u_boot_console): +def test_avb_mmc_uuid(ubman): """Check if 'avb get_uuid' works, compare results with 'part list mmc 1' output """ - response = u_boot_console.run_command('avb init %s' % str(mmc_dev)) + response = ubman.run_command('avb init %s' % str(mmc_dev)) assert response == '' - response = u_boot_console.run_command('mmc rescan; mmc dev %s' % + response = ubman.run_command('mmc rescan; mmc dev %s' % str(mmc_dev)) assert response.find('is current device') - part_lines = u_boot_console.run_command('mmc part').splitlines() + part_lines = ubman.run_command('mmc part').splitlines() part_list = {} cur_partname = '' @@ -67,72 +67,72 @@ def test_avb_mmc_uuid(u_boot_console): # lets check all guids with avb get_guid for part, guid in part_list.items(): - avb_guid_resp = u_boot_console.run_command('avb get_uuid %s' % part) + avb_guid_resp = ubman.run_command('avb get_uuid %s' % part) assert guid == avb_guid_resp.split('UUID: ')[1] @pytest.mark.buildconfigspec('cmd_avb') -def test_avb_read_rb(u_boot_console): +def test_avb_read_rb(ubman): """Test reading rollback indexes """ - response = u_boot_console.run_command('avb init %s' % str(mmc_dev)) + response = ubman.run_command('avb init %s' % str(mmc_dev)) assert response == '' - response = u_boot_console.run_command('avb read_rb 1') + response = ubman.run_command('avb read_rb 1') assert response == 'Rollback index: 0' @pytest.mark.buildconfigspec('cmd_avb') -def test_avb_is_unlocked(u_boot_console): +def test_avb_is_unlocked(ubman): """Test if device is in the unlocked state """ - response = u_boot_console.run_command('avb init %s' % str(mmc_dev)) + response = ubman.run_command('avb init %s' % str(mmc_dev)) assert response == '' - response = u_boot_console.run_command('avb is_unlocked') + response = ubman.run_command('avb is_unlocked') assert response == 'Unlocked = 1' @pytest.mark.buildconfigspec('cmd_avb') @pytest.mark.buildconfigspec('cmd_mmc') @pytest.mark.notbuildconfigspec('sandbox') -def test_avb_mmc_read(u_boot_console): +def test_avb_mmc_read(ubman): """Test mmc read operation """ - response = u_boot_console.run_command('mmc rescan; mmc dev %s 0' % + response = ubman.run_command('mmc rescan; mmc dev %s 0' % str(mmc_dev)) assert response.find('is current device') - response = u_boot_console.run_command('mmc read 0x%x 0x100 0x1' % temp_addr) + response = ubman.run_command('mmc read 0x%x 0x100 0x1' % temp_addr) assert response.find('read: OK') - response = u_boot_console.run_command('avb init %s' % str(mmc_dev)) + response = ubman.run_command('avb init %s' % str(mmc_dev)) assert response == '' - response = u_boot_console.run_command('avb read_part xloader 0 100 0x%x' % + response = ubman.run_command('avb read_part xloader 0 100 0x%x' % temp_addr2) assert response.find('Read 512 bytes') # Now lets compare two buffers - response = u_boot_console.run_command('cmp 0x%x 0x%x 40' % + response = ubman.run_command('cmp 0x%x 0x%x 40' % (temp_addr, temp_addr2)) assert response.find('64 word') @pytest.mark.buildconfigspec('cmd_avb') @pytest.mark.buildconfigspec('optee_ta_avb') -def test_avb_persistent_values(u_boot_console): +def test_avb_persistent_values(ubman): """Test reading/writing persistent storage to avb """ - response = u_boot_console.run_command('avb init %s' % str(mmc_dev)) + response = ubman.run_command('avb init %s' % str(mmc_dev)) assert response == '' - response = u_boot_console.run_command('avb write_pvalue test value_value') + response = ubman.run_command('avb write_pvalue test value_value') assert response == 'Wrote 12 bytes' - response = u_boot_console.run_command('avb read_pvalue test 12') + response = ubman.run_command('avb read_pvalue test 12') assert response == 'Read 12 bytes, value = value_value' -- cgit v1.3.1 From d9ed4b75add4b4ccc37cf32b54cd9c77f48e3396 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 9 Feb 2025 09:07:15 -0700 Subject: test/py: Drop u_boot_ prefix on test files We know this is U-Boot so the prefix serves no purpose other than to make things longer and harder to read. Drop it and rename the files. Signed-off-by: Simon Glass Reviewed-by: Mattijs Korpershoek # test_android / test_dfu --- doc/develop/py_testing.rst | 4 +- doc/develop/tests_writing.rst | 2 +- test/py/conftest.py | 52 +-- test/py/console_base.py | 613 ++++++++++++++++++++++++++++ test/py/console_board.py | 85 ++++ test/py/console_sandbox.py | 119 ++++++ test/py/spawn.py | 345 ++++++++++++++++ test/py/tests/test_android/test_ab.py | 12 +- test/py/tests/test_android/test_abootimg.py | 10 +- test/py/tests/test_android/test_avb.py | 2 +- test/py/tests/test_dfu.py | 18 +- test/py/tests/test_efi_fit.py | 2 +- test/py/tests/test_efi_loader.py | 4 +- test/py/tests/test_env.py | 24 +- test/py/tests/test_event_dump.py | 2 +- test/py/tests/test_extension.py | 2 +- test/py/tests/test_fit.py | 2 +- test/py/tests/test_fit_auto_signed.py | 2 +- test/py/tests/test_fit_ecdsa.py | 2 +- test/py/tests/test_fit_hashes.py | 2 +- test/py/tests/test_fpga.py | 8 +- test/py/tests/test_fs/conftest.py | 2 +- test/py/tests/test_gpio.py | 2 +- test/py/tests/test_gpt.py | 14 +- test/py/tests/test_kconfig.py | 2 +- test/py/tests/test_md.py | 6 +- test/py/tests/test_mmc.py | 8 +- test/py/tests/test_mmc_rd.py | 4 +- test/py/tests/test_mmc_wr.py | 4 +- test/py/tests/test_net.py | 6 +- test/py/tests/test_net_boot.py | 4 +- test/py/tests/test_of_migrate.py | 2 +- test/py/tests/test_ofplatdata.py | 2 +- test/py/tests/test_optee_rpmb.py | 2 +- test/py/tests/test_pinmux.py | 2 +- test/py/tests/test_pstore.py | 2 +- test/py/tests/test_sandbox_opts.py | 2 +- test/py/tests/test_scp03.py | 2 +- test/py/tests/test_sf.py | 12 +- test/py/tests/test_source.py | 2 +- test/py/tests/test_spi.py | 14 +- test/py/tests/test_tpm2.py | 10 +- test/py/tests/test_trace.py | 2 +- test/py/tests/test_ums.py | 21 +- test/py/tests/test_upl.py | 2 +- test/py/tests/test_usb.py | 12 +- test/py/tests/test_ut.py | 86 ++-- test/py/tests/test_vbe_vpl.py | 10 +- test/py/tests/test_vboot.py | 2 +- test/py/tests/test_zynq_secure.py | 12 +- test/py/tests/test_zynqmp_secure.py | 8 +- test/py/u_boot_console_base.py | 613 ---------------------------- test/py/u_boot_console_exec_attach.py | 85 ---- test/py/u_boot_console_sandbox.py | 119 ------ test/py/u_boot_spawn.py | 345 ---------------- test/py/u_boot_utils.py | 382 ----------------- test/py/utils.py | 382 +++++++++++++++++ 57 files changed, 1748 insertions(+), 1749 deletions(-) create mode 100644 test/py/console_base.py create mode 100644 test/py/console_board.py create mode 100644 test/py/console_sandbox.py create mode 100644 test/py/spawn.py delete mode 100644 test/py/u_boot_console_base.py delete mode 100644 test/py/u_boot_console_exec_attach.py delete mode 100644 test/py/u_boot_console_sandbox.py delete mode 100644 test/py/u_boot_spawn.py delete mode 100644 test/py/u_boot_utils.py create mode 100644 test/py/utils.py (limited to 'test/py/tests/test_android') diff --git a/doc/develop/py_testing.rst b/doc/develop/py_testing.rst index b88d7e3c8d4..40a85380343 100644 --- a/doc/develop/py_testing.rst +++ b/doc/develop/py_testing.rst @@ -125,7 +125,7 @@ browser, but may be read directly as plain text, perhaps with the aid of the If sandbox crashes (e.g. with a segfault) you will see message like this:: - test/py/u_boot_spawn.py:171: in expect + test/py/spawn.py:171: in expect c = os.read(self.fd, 1024).decode(errors='replace') E ValueError: U-Boot exited with signal 11 (Signals.SIGSEGV) @@ -515,7 +515,7 @@ U-Boot console, and returns all output from that command. This allows validation or interpretation of the command output. This function validates that certain strings are not seen on the U-Boot console. These include shell error messages and the U-Boot sign-on message (in order to detect unexpected -board resets). See the source of `u_boot_console_base.py` for a complete list of +board resets). See the source of `console_base.py` for a complete list of "bad" strings. Some test scenarios are expected to trigger these strings. Use `ubman.disable_check()` to temporarily disable checking for specific strings. See `test_unknown_cmd.py` for an example. diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst index d5917fe674c..7ea17081def 100644 --- a/doc/develop/tests_writing.rst +++ b/doc/develop/tests_writing.rst @@ -120,7 +120,7 @@ in Python:: """Test that md reads memory as expected, and that memory can be modified using the mw command.""" - ram_base = u_boot_utils.find_ram_base(ubman) + ram_base = utils.find_ram_base(ubman) addr = '%08x' % ram_base val = 'a5f09876' expected_response = addr + ': ' + val diff --git a/test/py/conftest.py b/test/py/conftest.py index 863f56c1152..8d0e786ee5c 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -7,7 +7,7 @@ # test, at shutdown etc. These hooks perform functions such as: # - Parsing custom command-line options. # - Pullilng in user-specified board configuration. -# - Creating the U-Boot console test fixture. +# - Creating the ubman test fixture. # - Creating the HTML log file. # - Monitoring each test's results. # - Implementing custom pytest markers. @@ -25,12 +25,12 @@ import re from _pytest.runner import runtestprotocol import subprocess import sys +from spawn import BootFail, Timeout, Unexpected, handle_exception import time -from u_boot_spawn import BootFail, Timeout, Unexpected, handle_exception -# Globals: The HTML log file, and the connection to the U-Boot console. +# Globals: The HTML log file, and the top-level fixture log = None -console = None +ubman_fix = None TEST_PY_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -247,7 +247,7 @@ def pytest_configure(config): ubconfig.buildconfig.update(parser.items('root')) global log - global console + global ubman_fix global ubconfig (board_type, board_type_extra, board_identity, build_dir, build_dir_extra, @@ -343,11 +343,11 @@ def pytest_configure(config): os.environ['U_BOOT_' + v.upper()] = getattr(ubconfig, v) if board_type.startswith('sandbox'): - import u_boot_console_sandbox - console = u_boot_console_sandbox.ConsoleSandbox(log, ubconfig) + import console_sandbox + ubman_fix = console_sandbox.ConsoleSandbox(log, ubconfig) else: - import u_boot_console_exec_attach - console = u_boot_console_exec_attach.ConsoleExecAttach(log, ubconfig) + import console_board + ubman_fix = console_board.ConsoleExecAttach(log, ubconfig) def generate_ut_subtest(metafunc, fixture_name, sym_path): @@ -366,7 +366,7 @@ def generate_ut_subtest(metafunc, fixture_name, sym_path): Returns: Nothing. """ - fn = console.config.build_dir + sym_path + fn = ubman_fix.config.build_dir + sym_path try: with open(fn, 'rt') as f: lines = f.readlines() @@ -407,8 +407,8 @@ def generate_config(metafunc, fixture_name): """ subconfigs = { - 'brd': console.config.brd, - 'env': console.config.env, + 'brd': ubman_fix.config.brd, + 'env': ubman_fix.config.env, } parts = fixture_name.split('__') if len(parts) < 2: @@ -470,7 +470,7 @@ def u_boot_log(request): The fixture value. """ - return console.log + return ubman_fix.log @pytest.fixture(scope='session') def u_boot_config(request): @@ -483,7 +483,7 @@ def u_boot_config(request): The fixture value. """ - return console.config + return ubman_fix.config @pytest.fixture(scope='function') def ubman(request): @@ -499,18 +499,18 @@ def ubman(request): pytest.skip('Cannot get target connection') return None try: - console.ensure_spawned() + ubman_fix.ensure_spawned() except OSError as err: - handle_exception(ubconfig, console, log, err, 'Lab failure', True) + handle_exception(ubconfig, ubman_fix, log, err, 'Lab failure', True) except Timeout as err: - handle_exception(ubconfig, console, log, err, 'Lab timeout', True) + handle_exception(ubconfig, ubman_fix, log, err, 'Lab timeout', True) except BootFail as err: - handle_exception(ubconfig, console, log, err, 'Boot fail', True, - console.get_spawn_output()) + handle_exception(ubconfig, ubman_fix, log, err, 'Boot fail', True, + ubman.get_spawn_output()) except Unexpected: - handle_exception(ubconfig, console, log, err, 'Unexpected test output', + handle_exception(ubconfig, ubman_fix, log, err, 'Unexpected test output', False) - return console + return ubman_fix anchors = {} tests_not_run = [] @@ -623,8 +623,8 @@ def cleanup(): Nothing. """ - if console: - console.close() + if ubman_fix: + ubman_fix.close() if log: with log.section('Status Report', 'status_report'): log.status_pass('%d passed' % len(tests_passed)) @@ -845,7 +845,7 @@ def pytest_runtest_protocol(item, nextitem): test_durations[item.name] = duration if failure_cleanup: - console.drain_console() + ubman_fix.drain_console() test_list.append(item.name) tests_not_run.remove(item.name) @@ -855,7 +855,7 @@ def pytest_runtest_protocol(item, nextitem): except: # If something went wrong with logging, it's better to let the test # process continue, which may report other exceptions that triggered - # the logging issue (e.g. console.log wasn't created). Hence, just + # the logging issue (e.g. ubman_fix.log wasn't created). Hence, just # squash the exception. If the test setup failed due to e.g. syntax # error somewhere else, this won't be seen. However, once that issue # is fixed, if this exception still exists, it will then be logged as @@ -868,6 +868,6 @@ def pytest_runtest_protocol(item, nextitem): log.end_section(item.name) if failure_cleanup: - console.cleanup_spawn() + ubman_fix.cleanup_spawn() return True diff --git a/test/py/console_base.py b/test/py/console_base.py new file mode 100644 index 00000000000..260df773bac --- /dev/null +++ b/test/py/console_base.py @@ -0,0 +1,613 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2015 Stephen Warren +# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. + +# Common logic to interact with U-Boot via the console. This class provides +# the interface that tests use to execute U-Boot shell commands and wait for +# their results. Sub-classes exist to perform board-type-specific setup +# operations, such as spawning a sub-process for Sandbox, or attaching to the +# serial console of real hardware. + +import multiplexed_log +import os +import pytest +import re +import sys +import spawn +from spawn import BootFail, Timeout, Unexpected, handle_exception + +# Regexes for text we expect U-Boot to send to the console. +pattern_u_boot_spl_signon = re.compile('(U-Boot SPL \\d{4}\\.\\d{2}[^\r\n]*\\))') +pattern_u_boot_main_signon = re.compile('(U-Boot \\d{4}\\.\\d{2}[^\r\n]*\\))') +pattern_stop_autoboot_prompt = re.compile('Hit any key to stop autoboot: ') +pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'') +pattern_error_notification = re.compile('## Error: ') +pattern_error_please_reset = re.compile('### ERROR ### Please RESET the board ###') +pattern_ready_prompt = re.compile('{lab ready in (.*)s: (.*)}') +pattern_lab_mode = re.compile('{lab mode.*}') + +PAT_ID = 0 +PAT_RE = 1 + +# Timeout before expecting the console to be ready (in milliseconds) +TIMEOUT_MS = 30000 # Standard timeout +TIMEOUT_CMD_MS = 10000 # Command-echo timeout + +# Timeout for board preparation in lab mode. This needs to be enough to build +# U-Boot, write it to the board and then boot the board. Since this process is +# under the control of another program (e.g. Labgrid), it will failure sooner +# if something goes way. So use a very long timeout here to cover all possible +# situations. +TIMEOUT_PREPARE_MS = 3 * 60 * 1000 + +bad_pattern_defs = ( + ('spl_signon', pattern_u_boot_spl_signon), + ('main_signon', pattern_u_boot_main_signon), + ('stop_autoboot_prompt', pattern_stop_autoboot_prompt), + ('unknown_command', pattern_unknown_command), + ('error_notification', pattern_error_notification), + ('error_please_reset', pattern_error_please_reset), +) + +class ConsoleDisableCheck(object): + """Context manager (for Python's with statement) that temporarily disables + the specified console output error check. This is useful when deliberately + executing a command that is known to trigger one of the error checks, in + order to test that the error condition is actually raised. This class is + used internally by ConsoleBase::disable_check(); it is not intended for + direct usage.""" + + def __init__(self, console, check_type): + self.console = console + self.check_type = check_type + + def __enter__(self): + self.console.disable_check_count[self.check_type] += 1 + self.console.eval_bad_patterns() + + def __exit__(self, extype, value, traceback): + self.console.disable_check_count[self.check_type] -= 1 + self.console.eval_bad_patterns() + +class ConsoleEnableCheck(object): + """Context manager (for Python's with statement) that temporarily enables + the specified console output error check. This is useful when executing a + command that might raise an extra bad pattern, beyond the default bad + patterns, in order to validate that the extra bad pattern is actually + detected. This class is used internally by ConsoleBase::enable_check(); it + is not intended for direct usage.""" + + def __init__(self, console, check_type, check_pattern): + self.console = console + self.check_type = check_type + self.check_pattern = check_pattern + + def __enter__(self): + global bad_pattern_defs + self.default_bad_patterns = bad_pattern_defs + bad_pattern_defs += ((self.check_type, self.check_pattern),) + self.console.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs} + self.console.eval_bad_patterns() + + def __exit__(self, extype, value, traceback): + global bad_pattern_defs + bad_pattern_defs = self.default_bad_patterns + self.console.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs} + self.console.eval_bad_patterns() + +class ConsoleSetupTimeout(object): + """Context manager (for Python's with statement) that temporarily sets up + timeout for specific command. This is useful when execution time is greater + then default 30s.""" + + def __init__(self, console, timeout): + self.p = console.p + self.orig_timeout = self.p.timeout + self.p.timeout = timeout + + def __enter__(self): + return self + + def __exit__(self, extype, value, traceback): + self.p.timeout = self.orig_timeout + +class ConsoleBase(object): + """The interface through which test functions interact with the U-Boot + console. This primarily involves executing shell commands, capturing their + results, and checking for common error conditions. Some common utilities + are also provided too.""" + + def __init__(self, log, config, max_fifo_fill): + """Initialize a U-Boot console connection. + + Can only usefully be called by sub-classes. + + Args: + log: A multiplexed_log.Logfile object, to which the U-Boot output + will be logged. + config: A configuration data structure, as built by conftest.py. + max_fifo_fill: The maximum number of characters to send to U-Boot + command-line before waiting for U-Boot to echo the characters + back. For UART-based HW without HW flow control, this value + should be set less than the UART RX FIFO size to avoid + overflow, assuming that U-Boot can't keep up with full-rate + traffic at the baud rate. + + Returns: + Nothing. + """ + + self.log = log + self.config = config + self.max_fifo_fill = max_fifo_fill + + self.logstream = self.log.get_stream('console', sys.stdout) + + # Array slice removes leading/trailing quotes + self.prompt = self.config.buildconfig['config_sys_prompt'][1:-1] + self.prompt_compiled = re.compile('^' + re.escape(self.prompt), re.MULTILINE) + self.p = None + self.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs} + self.eval_bad_patterns() + + self.at_prompt = False + self.at_prompt_logevt = None + self.lab_mode = False + + def get_spawn(self): + # This is not called, ssubclass must define this. + # Return a value to avoid: + # console_base.py:348:12: E1128: Assigning result of a function + # call, where the function returns None (assignment-from-none) + return spawn.Spawn([]) + + + def eval_bad_patterns(self): + self.bad_patterns = [pat[PAT_RE] for pat in bad_pattern_defs \ + if self.disable_check_count[pat[PAT_ID]] == 0] + self.bad_pattern_ids = [pat[PAT_ID] for pat in bad_pattern_defs \ + if self.disable_check_count[pat[PAT_ID]] == 0] + + def close(self): + """Terminate the connection to the U-Boot console. + + This function is only useful once all interaction with U-Boot is + complete. Once this function is called, data cannot be sent to or + received from U-Boot. + + Args: + None. + + Returns: + Nothing. + """ + + if self.p: + self.log.start_section('Stopping U-Boot') + close_type = self.p.close() + self.log.info(f'Close type: {close_type}') + self.log.end_section('Stopping U-Boot') + self.logstream.close() + + def set_lab_mode(self): + """Select lab mode + + This tells us that we will get a 'lab ready' message when the board is + ready for use. We don't need to look for signon messages. + """ + self.log.info(f'test.py: Lab mode is active') + self.p.timeout = TIMEOUT_PREPARE_MS + self.lab_mode = True + + def wait_for_boot_prompt(self, loop_num = 1): + """Wait for the boot up until command prompt. This is for internal use only. + """ + try: + self.log.info('Waiting for U-Boot to be ready') + bcfg = self.config.buildconfig + config_spl_serial = bcfg.get('config_spl_serial', 'n') == 'y' + env_spl_skipped = self.config.env.get('env__spl_skipped', False) + env_spl_banner_times = self.config.env.get('env__spl_banner_times', 1) + + while not self.lab_mode and loop_num > 0: + loop_num -= 1 + while config_spl_serial and not env_spl_skipped and env_spl_banner_times > 0: + m = self.p.expect([pattern_u_boot_spl_signon, + pattern_lab_mode] + self.bad_patterns) + if m == 1: + self.set_lab_mode() + break + elif m != 0: + raise BootFail('Bad pattern found on SPL console: ' + + self.bad_pattern_ids[m - 1]) + env_spl_banner_times -= 1 + + if not self.lab_mode: + m = self.p.expect([pattern_u_boot_main_signon, + pattern_lab_mode] + self.bad_patterns) + if m == 1: + self.set_lab_mode() + elif m != 0: + raise BootFail('Bad pattern found on console: ' + + self.bad_pattern_ids[m - 1]) + if not self.lab_mode: + self.u_boot_version_string = self.p.after + while True: + m = self.p.expect([self.prompt_compiled, pattern_ready_prompt, + pattern_stop_autoboot_prompt] + self.bad_patterns) + if m == 0: + self.log.info(f'Found ready prompt {m}') + break + elif m == 1: + m = pattern_ready_prompt.search(self.p.after) + self.u_boot_version_string = m.group(2) + self.log.info(f'Lab: Board is ready') + self.p.timeout = TIMEOUT_MS + break + if m == 2: + self.log.info(f'Found autoboot prompt {m}') + self.p.send(' ') + continue + if not self.lab_mode: + raise BootFail('Missing prompt / ready message on console: ' + + self.bad_pattern_ids[m - 3]) + self.log.info(f'U-Boot is ready') + + finally: + self.log.timestamp() + + def run_command(self, cmd, wait_for_echo=True, send_nl=True, + wait_for_prompt=True, wait_for_reboot=False): + """Execute a command via the U-Boot console. + + The command is always sent to U-Boot. + + U-Boot echoes any command back to its output, and this function + typically waits for that to occur. The wait can be disabled by setting + wait_for_echo=False, which is useful e.g. when sending CTRL-C to + interrupt a long-running command such as "ums". + + Command execution is typically triggered by sending a newline + character. This can be disabled by setting send_nl=False, which is + also useful when sending CTRL-C. + + This function typically waits for the command to finish executing, and + returns the console output that it generated. This can be disabled by + setting wait_for_prompt=False, which is useful when invoking a long- + running command such as "ums". + + Args: + cmd: The command to send. + wait_for_echo: Boolean indicating whether to wait for U-Boot to + echo the command text back to its output. + send_nl: Boolean indicating whether to send a newline character + after the command string. + wait_for_prompt: Boolean indicating whether to wait for the + command prompt to be sent by U-Boot. This typically occurs + immediately after the command has been executed. + wait_for_reboot: Boolean indication whether to wait for the + reboot U-Boot. If this sets True, wait_for_prompt must also + be True. + + Returns: + If wait_for_prompt == False: + Nothing. + Else: + The output from U-Boot during command execution. In other + words, the text U-Boot emitted between the point it echod the + command string and emitted the subsequent command prompts. + """ + + if self.at_prompt and \ + self.at_prompt_logevt != self.logstream.logfile.cur_evt: + self.logstream.write(self.prompt, implicit=True) + + try: + self.at_prompt = False + if not self.p: + raise BootFail( + f"Lab failure: Connection lost when sending command '{cmd}'") + + if send_nl: + cmd += '\n' + rem = cmd # Remaining to be sent + with self.temporary_timeout(TIMEOUT_CMD_MS): + while rem: + # Limit max outstanding data, so UART FIFOs don't overflow + chunk = rem[:self.max_fifo_fill] + rem = rem[self.max_fifo_fill:] + self.p.send(chunk) + if not wait_for_echo: + continue + chunk = re.escape(chunk) + chunk = chunk.replace('\\\n', '[\r\n]') + m = self.p.expect([chunk] + self.bad_patterns) + if m != 0: + self.at_prompt = False + raise BootFail(f"Failed to get echo on console (cmd '{cmd}':rem '{rem}'): " + + self.bad_pattern_ids[m - 1]) + if not wait_for_prompt: + return + if wait_for_reboot: + self.wait_for_boot_prompt() + else: + m = self.p.expect([self.prompt_compiled] + self.bad_patterns) + if m != 0: + self.at_prompt = False + raise BootFail('Missing prompt on console: ' + + self.bad_pattern_ids[m - 1]) + self.at_prompt = True + self.at_prompt_logevt = self.logstream.logfile.cur_evt + # Only strip \r\n; space/TAB might be significant if testing + # indentation. + return self.p.before.strip('\r\n') + except Timeout as exc: + handle_exception(self.config, self, self.log, exc, + f"Lab failure: Timeout executing '{cmd}'", True) + raise + except BootFail as exc: + handle_exception(self.config, self, self.log, exc, + f"'Boot fail '{cmd}'", + True, self.get_spawn_output()) + raise + finally: + self.log.timestamp() + + def run_command_list(self, cmds): + """Run a list of commands. + + This is a helper function to call run_command() with default arguments + for each command in a list. + + Args: + cmd: List of commands (each a string). + Returns: + A list of output strings from each command, one element for each + command. + """ + output = [] + for cmd in cmds: + output.append(self.run_command(cmd)) + return output + + def ctrlc(self): + """Send a CTRL-C character to U-Boot. + + This is useful in order to stop execution of long-running synchronous + commands such as "ums". + + Args: + None. + + Returns: + Nothing. + """ + + self.log.action('Sending Ctrl-C') + self.run_command(chr(3), wait_for_echo=False, send_nl=False) + + def wait_for(self, text): + """Wait for a pattern to be emitted by U-Boot. + + This is useful when a long-running command such as "dfu" is executing, + and it periodically emits some text that should show up at a specific + location in the log file. + + Args: + text: The text to wait for; either a string (containing raw text, + not a regular expression) or an re object. + + Returns: + Nothing. + """ + + if type(text) == type(''): + text = re.escape(text) + m = self.p.expect([text] + self.bad_patterns) + if m != 0: + raise Unexpected( + "Unexpected pattern found on console (exp '{text}': " + + self.bad_pattern_ids[m - 1]) + + def drain_console(self): + """Read from and log the U-Boot console for a short time. + + U-Boot's console output is only logged when the test code actively + waits for U-Boot to emit specific data. There are cases where tests + can fail without doing this. For example, if a test asks U-Boot to + enable USB device mode, then polls until a host-side device node + exists. In such a case, it is useful to log U-Boot's console output + in case U-Boot printed clues as to why the host-side even did not + occur. This function will do that. + + Args: + None. + + Returns: + Nothing. + """ + + # If we are already not connected to U-Boot, there's nothing to drain. + # This should only happen when a previous call to run_command() or + # wait_for() failed (and hence the output has already been logged), or + # the system is shutting down. + if not self.p: + return + + orig_timeout = self.p.timeout + try: + # Drain the log for a relatively short time. + self.p.timeout = 1000 + # Wait for something U-Boot will likely never send. This will + # cause the console output to be read and logged. + self.p.expect(['This should never match U-Boot output']) + except: + # We expect a timeout, since U-Boot won't print what we waited + # for. Squash it when it happens. + # + # Squash any other exception too. This function is only used to + # drain (and log) the U-Boot console output after a failed test. + # The U-Boot process will be restarted, or target board reset, once + # this function returns. So, we don't care about detecting any + # additional errors, so they're squashed so that the rest of the + # post-test-failure cleanup code can continue operation, and + # correctly terminate any log sections, etc. + pass + finally: + self.p.timeout = orig_timeout + + def ensure_spawned(self, expect_reset=False): + """Ensure a connection to a correctly running U-Boot instance. + + This may require spawning a new Sandbox process or resetting target + hardware, as defined by the implementation sub-class. + + This is an internal function and should not be called directly. + + Args: + expect_reset: Boolean indication whether this boot is expected + to be reset while the 1st boot process after main boot before + prompt. False by default. + + Returns: + Nothing. + """ + + if self.p: + # Reset the console timeout value as some tests may change + # its default value during the execution + if not self.config.gdbserver: + self.p.timeout = TIMEOUT_MS + return + try: + self.log.start_section('Starting U-Boot') + self.at_prompt = False + self.p = self.get_spawn() + # Real targets can take a long time to scroll large amounts of + # text if LCD is enabled. This value may need tweaking in the + # future, possibly per-test to be optimal. This works for 'help' + # on board 'seaboard'. + if not self.config.gdbserver: + self.p.timeout = TIMEOUT_MS + self.p.logfile_read = self.logstream + if self.config.use_running_system: + # Send an empty command to set up the 'expect' logic. This has + # the side effect of ensuring that there was no partial command + # line entered + self.run_command(' ') + else: + if expect_reset: + loop_num = 2 + else: + loop_num = 1 + self.wait_for_boot_prompt(loop_num = loop_num) + self.at_prompt = True + self.at_prompt_logevt = self.logstream.logfile.cur_evt + except Exception as ex: + self.log.error(str(ex)) + self.cleanup_spawn() + raise + finally: + self.log.timestamp() + self.log.end_section('Starting U-Boot') + + def cleanup_spawn(self): + """Shut down all interaction with the U-Boot instance. + + This is used when an error is detected prior to re-establishing a + connection with a fresh U-Boot instance. + + This is an internal function and should not be called directly. + + Args: + None. + + Returns: + Nothing. + """ + + try: + if self.p: + self.p.close() + except: + pass + self.p = None + + def restart_uboot(self, expect_reset=False): + """Shut down and restart U-Boot.""" + self.cleanup_spawn() + self.ensure_spawned(expect_reset) + + def get_spawn_output(self): + """Return the start-up output from U-Boot + + Returns: + The output produced by ensure_spawed(), as a string. + """ + if self.p: + return self.p.get_expect_output() + return None + + def validate_version_string_in_text(self, text): + """Assert that a command's output includes the U-Boot signon message. + + This is primarily useful for validating the "version" command without + duplicating the signon text regex in a test function. + + Args: + text: The command output text to check. + + Returns: + Nothing. An exception is raised if the validation fails. + """ + + assert(self.u_boot_version_string in text) + + def disable_check(self, check_type): + """Temporarily disable an error check of U-Boot's output. + + Create a new context manager (for use with the "with" statement) which + temporarily disables a particular console output error check. + + Args: + check_type: The type of error-check to disable. Valid values may + be found in self.disable_check_count above. + + Returns: + A context manager object. + """ + + return ConsoleDisableCheck(self, check_type) + + def enable_check(self, check_type, check_pattern): + """Temporarily enable an error check of U-Boot's output. + + Create a new context manager (for use with the "with" statement) which + temporarily enables a particular console output error check. The + arguments form a new element of bad_pattern_defs defined above. + + Args: + check_type: The type of error-check or bad pattern to enable. + check_pattern: The regexes for text error pattern or bad pattern + to be checked. + + Returns: + A context manager object. + """ + + return ConsoleEnableCheck(self, check_type, check_pattern) + + def temporary_timeout(self, timeout): + """Temporarily set up different timeout for commands. + + Create a new context manager (for use with the "with" statement) which + temporarily change timeout. + + Args: + timeout: Time in milliseconds. + + Returns: + A context manager object. + """ + + return ConsoleSetupTimeout(self, timeout) diff --git a/test/py/console_board.py b/test/py/console_board.py new file mode 100644 index 00000000000..bacb1e2526c --- /dev/null +++ b/test/py/console_board.py @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2015 Stephen Warren +# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. + +""" +Logic to interact with U-Boot running on real hardware, typically via a +physical serial port. +""" + +import sys +from spawn import Spawn +from console_base import ConsoleBase + +class ConsoleExecAttach(ConsoleBase): + """Represents a physical connection to a U-Boot console, typically via a + serial port. This implementation executes a sub-process to attach to the + console, expecting that the stdin/out of the sub-process will be forwarded + to/from the physical hardware. This approach isolates the test infra- + structure from the user-/installation-specific details of how to + communicate with, and the identity of, serial ports etc.""" + + def __init__(self, log, config): + """Initialize a U-Boot console connection. + + Args: + log: A multiplexed_log.Logfile instance. + config: A "configuration" object as defined in conftest.py. + + Returns: + Nothing. + """ + + # The max_fifo_fill value might need tweaking per-board/-SoC? + # 1 would be safe anywhere, but is very slow (a pexpect issue?). + # 16 is a common FIFO size. + # HW flow control would mean this could be infinite. + super(ConsoleExecAttach, self).__init__(log, config, max_fifo_fill=16) + + with self.log.section('flash'): + self.log.action('Flashing U-Boot') + cmd = ['u-boot-test-flash', config.board_type, config.board_identity] + runner = self.log.get_runner(cmd[0], sys.stdout) + runner.run(cmd) + runner.close() + self.log.status_pass('OK') + + def get_spawn(self): + """Connect to a fresh U-Boot instance. + + The target board is reset, so that U-Boot begins running from scratch. + + Args: + None. + + Returns: + A spawn.Spawn object that is attached to U-Boot. + """ + + args = [self.config.board_type, self.config.board_identity] + s = Spawn(['u-boot-test-console'] + args) + + if self.config.use_running_system: + self.log.action('Connecting to board without reset') + else: + try: + self.log.action('Resetting board') + cmd = ['u-boot-test-reset'] + args + runner = self.log.get_runner(cmd[0], sys.stdout) + runner.run(cmd) + runner.close() + except: + s.close() + raise + + return s + + def close(self): + super().close() + + self.log.action('Releasing board') + args = [self.config.board_type, self.config.board_identity] + cmd = ['u-boot-test-release'] + args + runner = self.log.get_runner(cmd[0], sys.stdout) + runner.run(cmd) + runner.close() diff --git a/test/py/console_sandbox.py b/test/py/console_sandbox.py new file mode 100644 index 00000000000..da55d2fcc1f --- /dev/null +++ b/test/py/console_sandbox.py @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2015 Stephen Warren +# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. + +""" +Logic to interact with the sandbox port of U-Boot, running as a sub-process. +""" + +import time +from spawn import Spawn +from console_base import ConsoleBase + +class ConsoleSandbox(ConsoleBase): + """Represents a connection to a sandbox U-Boot console, executed as a sub- + process.""" + + def __init__(self, log, config): + """Initialize a U-Boot console connection. + + Args: + log: A multiplexed_log.Logfile instance. + config: A "configuration" object as defined in conftest.py. + + Returns: + Nothing. + """ + + super(ConsoleSandbox, self).__init__(log, config, max_fifo_fill=1024) + self.sandbox_flags = [] + self.use_dtb = True + + def get_spawn(self): + """Connect to a fresh U-Boot instance. + + A new sandbox process is created, so that U-Boot begins running from + scratch. + + Args: + None. + + Returns: + A spawn.Spawn object that is attached to U-Boot. + """ + + bcfg = self.config.buildconfig + config_spl = bcfg.get('config_spl', 'n') == 'y' + config_vpl = bcfg.get('config_vpl', 'n') == 'y' + if config_vpl: + # Run TPL first, which runs VPL + fname = '/tpl/u-boot-tpl' + else: + fname = '/spl/u-boot-spl' if config_spl else '/u-boot' + print(fname) + cmd = [] + if self.config.gdbserver: + cmd += ['gdbserver', self.config.gdbserver] + cmd += [self.config.build_dir + fname, '-v'] + if self.use_dtb: + cmd += ['-d', self.config.dtb] + cmd += self.sandbox_flags + return Spawn(cmd, cwd=self.config.source_dir, decode_signal=True) + + def restart_uboot_with_flags(self, flags, expect_reset=False, use_dtb=True): + """Run U-Boot with the given command-line flags + + Args: + flags: List of flags to pass, each a string + expect_reset: Boolean indication whether this boot is expected + to be reset while the 1st boot process after main boot before + prompt. False by default. + use_dtb: True to use a device tree file, False to run without one + + Returns: + A spawn.Spawn object that is attached to U-Boot. + """ + + try: + self.sandbox_flags = flags + self.use_dtb = use_dtb + return self.restart_uboot(expect_reset) + finally: + self.sandbox_flags = [] + self.use_dtb = True + + def kill(self, sig): + """Send a specific Unix signal to the sandbox process. + + Args: + sig: The Unix signal to send to the process. + + Returns: + Nothing. + """ + + self.log.action('kill %d' % sig) + self.p.kill(sig) + + def validate_exited(self): + """Determine whether the sandbox process has exited. + + If required, this function waits a reasonable time for the process to + exit. + + Args: + None. + + Returns: + Boolean indicating whether the process has exited. + """ + + p = self.p + self.p = None + for i in range(100): + ret = not p.isalive() + if ret: + break + time.sleep(0.1) + p.close() + return ret diff --git a/test/py/spawn.py b/test/py/spawn.py new file mode 100644 index 00000000000..c703454389d --- /dev/null +++ b/test/py/spawn.py @@ -0,0 +1,345 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. + +""" +Logic to spawn a sub-process and interact with its stdio. +""" + +import io +import os +import re +import pty +import pytest +import signal +import select +import sys +import termios +import time +import traceback + +# Character to send (twice) to exit the terminal +EXIT_CHAR = 0x1d # FS (Ctrl + ]) + +class Timeout(Exception): + """An exception sub-class that indicates that a timeout occurred.""" + +class BootFail(Exception): + """An exception sub-class that indicates that a boot failure occurred. + + This is used when a bad pattern is seen when waiting for the boot prompt. + It is regarded as fatal, to avoid trying to boot the again and again to no + avail. + """ + +class Unexpected(Exception): + """An exception sub-class that indicates that unexpected test was seen.""" + + +def handle_exception(ubconfig, console, log, err, name, fatal, output=''): + """Handle an exception from the console + + Exceptions can occur when there is unexpected output or due to the board + crashing or hanging. Some exceptions are likely fatal, where retrying will + just chew up time to no available. In those cases it is best to cause + further tests be skipped. + + Args: + ubconfig (ArbitraryAttributeContainer): ubconfig object + log (Logfile): Place to log errors + console (ConsoleBase): Console to clean up, if fatal + err (Exception): Exception which was thrown + name (str): Name of problem, to log + fatal (bool): True to abort all tests + output (str): Extra output to report on boot failure. This can show the + target's console output as it tried to boot + """ + msg = f'{name}: ' + if fatal: + msg += 'Marking connection bad - no other tests will run' + else: + msg += 'Assuming that lab is healthy' + print(msg) + log.error(msg) + log.error(f'Error: {err}') + + if output: + msg += f'; output {output}' + + if fatal: + ubconfig.connection_ok = False + console.cleanup_spawn() + pytest.exit(msg) + + +class Spawn: + """Represents the stdio of a freshly created sub-process. Commands may be + sent to the process, and responses waited for. + + Members: + output: accumulated output from expect() + """ + + def __init__(self, args, cwd=None, decode_signal=False): + """Spawn (fork/exec) the sub-process. + + Args: + args: array of processs arguments. argv[0] is the command to + execute. + cwd: the directory to run the process in, or None for no change. + decode_signal (bool): True to indicate the exception number when + something goes wrong + + Returns: + Nothing. + """ + self.decode_signal = decode_signal + self.waited = False + self.exit_code = 0 + self.exit_info = '' + self.buf = '' + self.output = '' + self.logfile_read = None + self.before = '' + self.after = '' + self.timeout = None + # http://stackoverflow.com/questions/7857352/python-regex-to-match-vt100-escape-sequences + self.re_vt100 = re.compile(r'(\x1b\[|\x9b)[^@-_]*[@-_]|\x1b[@-_]', re.I) + + (self.pid, self.fd) = pty.fork() + if self.pid == 0: + try: + # For some reason, SIGHUP is set to SIG_IGN at this point when + # run under "go" (www.go.cd). Perhaps this happens under any + # background (non-interactive) system? + signal.signal(signal.SIGHUP, signal.SIG_DFL) + if cwd: + os.chdir(cwd) + os.execvp(args[0], args) + except: + print('CHILD EXECEPTION:') + traceback.print_exc() + finally: + os._exit(255) + + old = None + try: + isatty = False + try: + isatty = os.isatty(sys.stdout.fileno()) + + # with --capture=tee-sys we cannot call fileno() + except io.UnsupportedOperation as exc: + pass + if isatty: + new = termios.tcgetattr(self.fd) + old = new + new[3] = new[3] & ~(termios.ICANON | termios.ISIG) + new[3] = new[3] & ~termios.ECHO + new[6][termios.VMIN] = 0 + new[6][termios.VTIME] = 0 + termios.tcsetattr(self.fd, termios.TCSANOW, new) + + self.poll = select.poll() + self.poll.register(self.fd, select.POLLIN | select.POLLPRI | select.POLLERR | + select.POLLHUP | select.POLLNVAL) + except: + if old: + termios.tcsetattr(self.fd, termios.TCSANOW, old) + self.close() + raise + + def kill(self, sig): + """Send unix signal "sig" to the child process. + + Args: + sig: The signal number to send. + + Returns: + Nothing. + """ + + os.kill(self.pid, sig) + + def checkalive(self): + """Determine whether the child process is still running. + + Returns: + tuple: + True if process is alive, else False + 0 if process is alive, else exit code of process + string describing what happened ('' or 'status/signal n') + """ + + if self.waited: + return False, self.exit_code, self.exit_info + + w = os.waitpid(self.pid, os.WNOHANG) + if w[0] == 0: + return True, 0, 'running' + status = w[1] + + if os.WIFEXITED(status): + self.exit_code = os.WEXITSTATUS(status) + self.exit_info = 'status %d' % self.exit_code + elif os.WIFSIGNALED(status): + signum = os.WTERMSIG(status) + self.exit_code = -signum + self.exit_info = 'signal %d (%s)' % (signum, signal.Signals(signum).name) + self.waited = True + return False, self.exit_code, self.exit_info + + def isalive(self): + """Determine whether the child process is still running. + + Args: + None. + + Returns: + Boolean indicating whether process is alive. + """ + return self.checkalive()[0] + + def send(self, data): + """Send data to the sub-process's stdin. + + Args: + data: The data to send to the process. + + Returns: + Nothing. + """ + + os.write(self.fd, data.encode(errors='replace')) + + def receive(self, num_bytes): + """Receive data from the sub-process's stdin. + + Args: + num_bytes (int): Maximum number of bytes to read + + Returns: + str: The data received + + Raises: + ValueError if U-Boot died + """ + try: + c = os.read(self.fd, num_bytes).decode(errors='replace') + except OSError as err: + # With sandbox, try to detect when U-Boot exits when it + # shouldn't and explain why. This is much more friendly than + # just dying with an I/O error + if self.decode_signal and err.errno == 5: # I/O error + alive, _, info = self.checkalive() + if alive: + raise err + raise ValueError('U-Boot exited with %s' % info) + raise + return c + + def expect(self, patterns): + """Wait for the sub-process to emit specific data. + + This function waits for the process to emit one pattern from the + supplied list of patterns, or for a timeout to occur. + + Args: + patterns: A list of strings or regex objects that we expect to + see in the sub-process' stdout. + + Returns: + The index within the patterns array of the pattern the process + emitted. + + Notable exceptions: + Timeout, if the process did not emit any of the patterns within + the expected time. + """ + + for pi in range(len(patterns)): + if type(patterns[pi]) == type(''): + patterns[pi] = re.compile(patterns[pi]) + + tstart_s = time.time() + try: + while True: + earliest_m = None + earliest_pi = None + for pi in range(len(patterns)): + pattern = patterns[pi] + m = pattern.search(self.buf) + if not m: + continue + if earliest_m and m.start() >= earliest_m.start(): + continue + earliest_m = m + earliest_pi = pi + if earliest_m: + pos = earliest_m.start() + posafter = earliest_m.end() + self.before = self.buf[:pos] + self.after = self.buf[pos:posafter] + self.output += self.buf[:posafter] + self.buf = self.buf[posafter:] + return earliest_pi + tnow_s = time.time() + if self.timeout: + tdelta_ms = (tnow_s - tstart_s) * 1000 + poll_maxwait = self.timeout - tdelta_ms + if tdelta_ms > self.timeout: + raise Timeout() + else: + poll_maxwait = None + events = self.poll.poll(poll_maxwait) + if not events: + raise Timeout() + c = self.receive(1024) + if self.logfile_read: + self.logfile_read.write(c) + self.buf += c + # count=0 is supposed to be the default, which indicates + # unlimited substitutions, but in practice the version of + # Python in Ubuntu 14.04 appears to default to count=2! + self.buf = self.re_vt100.sub('', self.buf, count=1000000) + finally: + if self.logfile_read: + self.logfile_read.flush() + + def close(self): + """Close the stdio connection to the sub-process. + + This also waits a reasonable time for the sub-process to stop running. + + Args: + None. + + Returns: + str: Type of closure completed + """ + # For Labgrid-sjg, ask it is exit gracefully, so it can transition the + # board to the final state (like 'off') before exiting. + if os.environ.get('USE_LABGRID_SJG'): + self.send(chr(EXIT_CHAR) * 2) + + # Wait about 10 seconds for Labgrid to close and power off the board + for _ in range(100): + if not self.isalive(): + return 'normal' + time.sleep(0.1) + + # That didn't work, so try closing the PTY + os.close(self.fd) + for _ in range(100): + if not self.isalive(): + return 'break' + time.sleep(0.1) + + return 'timeout' + + def get_expect_output(self): + """Return the output read by expect() + + Returns: + The output processed by expect(), as a string. + """ + return self.output diff --git a/test/py/tests/test_android/test_ab.py b/test/py/tests/test_android/test_ab.py index 739b7ce695d..5876a137463 100644 --- a/test/py/tests/test_android/test_ab.py +++ b/test/py/tests/test_android/test_ab.py @@ -5,7 +5,7 @@ import os import pytest -import u_boot_utils +import utils class ABTestDiskImage(object): """Disk Image used by the A/B tests.""" @@ -25,7 +25,7 @@ class ABTestDiskImage(object): persistent = ubman.config.persistent_data_dir + '/' + filename self.path = ubman.config.result_dir + '/' + filename - with u_boot_utils.persistent_file_helper(ubman.log, persistent): + with utils.persistent_file_helper(ubman.log, persistent): if os.path.exists(persistent): ubman.log.action('Disk image file ' + persistent + ' already exists') @@ -35,16 +35,16 @@ class ABTestDiskImage(object): os.ftruncate(fd, 524288) os.close(fd) cmd = ('sgdisk', persistent) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) cmd = ('sgdisk', '--new=1:64:512', '--change-name=1:misc', persistent) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) cmd = ('sgdisk', '--load-backup=' + persistent) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) cmd = ('cp', persistent, self.path) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) di = None @pytest.fixture(scope='function') diff --git a/test/py/tests/test_android/test_abootimg.py b/test/py/tests/test_android/test_abootimg.py index fd3e08fa899..c31fb466ec7 100644 --- a/test/py/tests/test_android/test_abootimg.py +++ b/test/py/tests/test_android/test_abootimg.py @@ -6,7 +6,7 @@ import os import pytest -import u_boot_utils +import utils """ These tests rely on disk image (boot.img), which is automatically created by @@ -122,7 +122,7 @@ class AbootimgTestDiskImage(object): persistent = ubman.config.persistent_data_dir + '/' + filename self.path = ubman.config.result_dir + '/' + filename ubman.log.action('persistent is ' + persistent) - with u_boot_utils.persistent_file_helper(ubman.log, persistent): + with utils.persistent_file_helper(ubman.log, persistent): if os.path.exists(persistent): ubman.log.action('Disk image file ' + persistent + ' already exists') @@ -133,12 +133,12 @@ class AbootimgTestDiskImage(object): f.write(hex_img) f.close() cmd = ('xxd', '-r', '-p', gz_hex, gz) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) cmd = ('gunzip', '-9', gz) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) cmd = ('cp', persistent, self.path) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) gtdi1 = None @pytest.fixture(scope='function') diff --git a/test/py/tests/test_android/test_avb.py b/test/py/tests/test_android/test_avb.py index 451a476da76..1d600b95c6f 100644 --- a/test/py/tests/test_android/test_avb.py +++ b/test/py/tests/test_android/test_avb.py @@ -15,7 +15,7 @@ For configuration verification: """ import pytest -import u_boot_utils as util +import utils as util # defauld mmc id mmc_dev = 1 diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py index 6efb69990d4..7d6f41db7fb 100644 --- a/test/py/tests/test_dfu.py +++ b/test/py/tests/test_dfu.py @@ -9,7 +9,7 @@ import os import os.path import pytest -import u_boot_utils +import utils """ Note: This test relies on: @@ -143,9 +143,9 @@ def test_dfu(ubman, env__usb_dev_port, env__dfu_config): Nothing. """ - u_boot_utils.wait_until_file_open_fails( + utils.wait_until_file_open_fails( env__usb_dev_port['host_usb_dev_node'], True) - fh = u_boot_utils.attempt_to_open_file( + fh = utils.attempt_to_open_file( env__usb_dev_port['host_usb_dev_node']) if fh: fh.close() @@ -164,7 +164,7 @@ def test_dfu(ubman, env__usb_dev_port, env__dfu_config): cmd = 'dfu 0 ' + env__dfu_config['cmd_params'] ubman.run_command(cmd, wait_for_prompt=False) ubman.log.action('Waiting for DFU USB device to appear') - fh = u_boot_utils.wait_until_open_succeeds( + fh = utils.wait_until_open_succeeds( env__usb_dev_port['host_usb_dev_node']) fh.close() @@ -190,7 +190,7 @@ def test_dfu(ubman, env__usb_dev_port, env__dfu_config): ubman.ctrlc() ubman.log.action( 'Waiting for DFU USB device to disappear') - u_boot_utils.wait_until_file_open_fails( + utils.wait_until_file_open_fails( env__usb_dev_port['host_usb_dev_node'], ignore_errors) except: if not ignore_errors: @@ -213,7 +213,7 @@ def test_dfu(ubman, env__usb_dev_port, env__dfu_config): cmd = ['dfu-util', '-a', 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(ubman, cmd) + utils.run_and_log(ubman, cmd) ubman.wait_for('Ctrl+C to exit ...') def dfu_write(alt_setting, fn): @@ -261,7 +261,7 @@ def test_dfu(ubman, env__usb_dev_port, env__dfu_config): Nothing. """ - test_f = u_boot_utils.PersistentRandomFile(ubman, + test_f = utils.PersistentRandomFile(ubman, 'dfu_%d.bin' % size, size) readback_fn = ubman.config.result_dir + '/dfu_readback.bin' @@ -279,7 +279,7 @@ def test_dfu(ubman, env__usb_dev_port, env__dfu_config): ubman.log.action('Comparing written and read data') written_hash = test_f.content_hash - read_back_hash = u_boot_utils.md5sum_file(readback_fn, size) + read_back_hash = 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 @@ -295,7 +295,7 @@ def test_dfu(ubman, env__usb_dev_port, env__dfu_config): else: sizes = [] - dummy_f = u_boot_utils.PersistentRandomFile(ubman, + dummy_f = utils.PersistentRandomFile(ubman, 'dfu_dummy.bin', 1024) alt_setting_test_file = env__dfu_config.get('alt_id_test_file', '0') diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py index 4a464382126..c836834845e 100644 --- a/test/py/tests/test_efi_fit.py +++ b/test/py/tests/test_efi_fit.py @@ -55,7 +55,7 @@ env__efi_fit_tftp_file = { import os.path import pytest -import u_boot_utils as util +import utils as util # Define the parametrized ITS data to be used for FIT images generation. ITS_DATA = ''' diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py index ff880ffa527..58f2655191f 100644 --- a/test/py/tests/test_efi_loader.py +++ b/test/py/tests/test_efi_loader.py @@ -53,7 +53,7 @@ env__efi_helloworld_net_http_test_skip = True """ import pytest -import u_boot_utils +import utils PROTO_TFTP, PROTO_HTTP = range(0, 2) @@ -132,7 +132,7 @@ def fetch_file(ubman, env_conf, proto): addr = f.get('addr', None) if not addr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) fn = f['fn'] if proto == PROTO_TFTP: diff --git a/test/py/tests/test_env.py b/test/py/tests/test_env.py index 6f75e107bbe..376ea7b78b8 100644 --- a/test/py/tests/test_env.py +++ b/test/py/tests/test_env.py @@ -13,7 +13,7 @@ from subprocess import call, CalledProcessError import tempfile import pytest -import u_boot_utils +import utils # FIXME: This might be useful for other tests; # perhaps refactor it into ConsoleBase or some other state object? @@ -187,7 +187,7 @@ def test_env_initial_env_file(ubman): except: pass - u_boot_utils.run_and_log(cons, ['make', builddir, 'u-boot-initial-env']) + utils.run_and_log(cons, ['make', builddir, 'u-boot-initial-env']) assert os.path.exists(envfile) @@ -278,7 +278,7 @@ def test_env_import_checksum_no_size(state_test_env): env import function. """ c = state_test_env.ubman - ram_base = u_boot_utils.find_ram_base(state_test_env.ubman) + ram_base = utils.find_ram_base(state_test_env.ubman) addr = '%08x' % ram_base with c.disable_check('error_notification'): @@ -291,7 +291,7 @@ def test_env_import_whitelist_checksum_no_size(state_test_env): env import function when variables are passed as parameters. """ c = state_test_env.ubman - ram_base = u_boot_utils.find_ram_base(state_test_env.ubman) + ram_base = utils.find_ram_base(state_test_env.ubman) addr = '%08x' % ram_base with c.disable_check('error_notification'): @@ -303,7 +303,7 @@ def test_env_import_whitelist_checksum_no_size(state_test_env): def test_env_import_whitelist(state_test_env): """Test importing only a handful of env variables from an environment.""" c = state_test_env.ubman - ram_base = u_boot_utils.find_ram_base(state_test_env.ubman) + ram_base = utils.find_ram_base(state_test_env.ubman) addr = '%08x' % ram_base set_var(state_test_env, 'foo1', 'bar1') @@ -340,7 +340,7 @@ def test_env_import_whitelist_delete(state_test_env): environment to be imported. """ c = state_test_env.ubman - ram_base = u_boot_utils.find_ram_base(state_test_env.ubman) + ram_base = utils.find_ram_base(state_test_env.ubman) addr = '%08x' % ram_base set_var(state_test_env, 'foo1', 'bar1') @@ -446,16 +446,16 @@ def mk_env_ext4(state_test_env): # Some distributions do not add /sbin to the default PATH, where mkfs.ext4 lives os.environ["PATH"] += os.pathsep + '/sbin' try: - u_boot_utils.run_and_log(c, 'dd if=/dev/zero of=%s bs=1M count=16' % persistent) - u_boot_utils.run_and_log(c, 'mkfs.ext4 %s' % persistent) - sb_content = u_boot_utils.run_and_log(c, 'tune2fs -l %s' % persistent) + utils.run_and_log(c, 'dd if=/dev/zero of=%s bs=1M count=16' % persistent) + utils.run_and_log(c, 'mkfs.ext4 %s' % persistent) + sb_content = utils.run_and_log(c, 'tune2fs -l %s' % persistent) if 'metadata_csum' in sb_content: - u_boot_utils.run_and_log(c, 'tune2fs -O ^metadata_csum %s' % persistent) + utils.run_and_log(c, 'tune2fs -O ^metadata_csum %s' % persistent) except CalledProcessError: call('rm -f %s' % persistent, shell=True) raise - u_boot_utils.run_and_log(c, ['cp', '-f', persistent, fs_img]) + utils.run_and_log(c, ['cp', '-f', persistent, fs_img]) return fs_img @pytest.mark.boardspec('sandbox') @@ -560,7 +560,7 @@ def test_env_text(ubman): fname = os.path.join(path, 'infile') with open(fname, 'w') as inf: print(intext, file=inf) - result = u_boot_utils.run_and_log(cons, ['awk', '-f', script, fname]) + result = utils.run_and_log(cons, ['awk', '-f', script, fname]) if expect_val is not None: expect = '#define CONFIG_EXTRA_ENV_TEXT "%s"\n' % expect_val assert result == expect diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py index 3f8ba647848..5a9d39da74c 100644 --- a/test/py/tests/test_event_dump.py +++ b/test/py/tests/test_event_dump.py @@ -4,7 +4,7 @@ import pytest import re -import u_boot_utils as util +import utils as util # This is only a partial test - coverting 64-bit sandbox. It does not test # big-endian images, nor 32-bit images diff --git a/test/py/tests/test_extension.py b/test/py/tests/test_extension.py index d0840f779bc..61223496054 100644 --- a/test/py/tests/test_extension.py +++ b/test/py/tests/test_extension.py @@ -6,7 +6,7 @@ import os import pytest -import u_boot_utils +import utils overlay_addr = 0x1000 diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 459be5af39d..0f2d0940562 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -6,7 +6,7 @@ import os import pytest import struct -import u_boot_utils as util +import utils as util import fit_util # Define a base ITS which we can adjust using % and a dictionary diff --git a/test/py/tests/test_fit_auto_signed.py b/test/py/tests/test_fit_auto_signed.py index 72f39edacf8..bee93e4f084 100644 --- a/test/py/tests/test_fit_auto_signed.py +++ b/test/py/tests/test_fit_auto_signed.py @@ -17,7 +17,7 @@ The test does not run the sandbox. It only checks the host tool mkimage. import os import pytest -import u_boot_utils as util +import utils as util import binascii from Cryptodome.Hash import SHA1 from Cryptodome.Hash import SHA256 diff --git a/test/py/tests/test_fit_ecdsa.py b/test/py/tests/test_fit_ecdsa.py index 428d3e76a18..7b25c7779c6 100644 --- a/test/py/tests/test_fit_ecdsa.py +++ b/test/py/tests/test_fit_ecdsa.py @@ -12,7 +12,7 @@ This test doesn't run the sandbox. It only checks the host tool 'mkimage' import os import pytest -import u_boot_utils as util +import utils as util from Cryptodome.Hash import SHA256 from Cryptodome.PublicKey import ECC from Cryptodome.Signature import DSS diff --git a/test/py/tests/test_fit_hashes.py b/test/py/tests/test_fit_hashes.py index 7bc24a7c870..0b3c85f8e23 100644 --- a/test/py/tests/test_fit_hashes.py +++ b/test/py/tests/test_fit_hashes.py @@ -12,7 +12,7 @@ This test doesn't run the sandbox. It only checks the host tool 'mkimage' import os import pytest -import u_boot_utils as util +import utils as util kernel_hashes = { "sha512" : "f18c1486a2c29f56360301576cdfce4dfd8e8e932d0ed8e239a1f314b8ae1d77b2a58cd7fe32e4075e69448e623ce53b0b6aa6ce5626d2c189a5beae29a68d93", diff --git a/test/py/tests/test_fpga.py b/test/py/tests/test_fpga.py index 7450b13945f..74cd42b910e 100644 --- a/test/py/tests/test_fpga.py +++ b/test/py/tests/test_fpga.py @@ -8,7 +8,7 @@ import pytest import re import random -import u_boot_utils +import utils """ Note: This test relies on boardenv_* containing configuration values to define @@ -518,7 +518,7 @@ def test_fpga_secure_bit_auth(ubman): addr = f.get('addr', None) if not addr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' fn = f['fn'] @@ -546,7 +546,7 @@ def test_fpga_secure_bit_img_auth_kup(ubman): keyaddr = f.get('keyaddr', None) if not keyaddr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' keyfn = f['keyfn'] output = ubman.run_command('tftpboot %x %s' % (keyaddr, keyfn)) @@ -554,7 +554,7 @@ def test_fpga_secure_bit_img_auth_kup(ubman): addr = f.get('addr', None) if not addr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' fn = f['enckupfn'] output = ubman.run_command('tftpboot %x %s' % (addr, fn)) diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py index 7bfcf41ed6f..5b259796ebe 100644 --- a/test/py/tests/test_fs/conftest.py +++ b/test/py/tests/test_fs/conftest.py @@ -8,7 +8,7 @@ import pytest import re from subprocess import call, check_call, check_output, CalledProcessError from fstest_defs import * -import u_boot_utils as util +import utils as util # pylint: disable=E0611 from tests import fs_helper diff --git a/test/py/tests/test_gpio.py b/test/py/tests/test_gpio.py index 5c9d0b60bf5..46b674b7653 100644 --- a/test/py/tests/test_gpio.py +++ b/test/py/tests/test_gpio.py @@ -5,7 +5,7 @@ import pytest import time -import u_boot_utils +import utils """ test_gpio_input is intended to test the fix 4dbc107f4683. diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py index 0bd6a21278a..cfc8f1319a9 100644 --- a/test/py/tests/test_gpt.py +++ b/test/py/tests/test_gpt.py @@ -6,7 +6,7 @@ import os import pytest -import u_boot_utils +import utils """ These tests rely on a 4 MB disk image, which is automatically created by @@ -63,7 +63,7 @@ class GptTestDiskImage(object): persistent = ubman.config.persistent_data_dir + '/' + filename self.path = ubman.config.result_dir + '/' + filename - with u_boot_utils.persistent_file_helper(ubman.log, persistent): + with utils.persistent_file_helper(ubman.log, persistent): if os.path.exists(persistent): ubman.log.action('Disk image file ' + persistent + ' already exists') @@ -75,23 +75,23 @@ class GptTestDiskImage(object): cmd = ('sgdisk', '--disk-guid=375a56f7-d6c9-4e81-b5f0-09d41ca89efe', persistent) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) # part1 offset 1MB size 1MB cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1', '--partition-guid=1:33194895-67f6-4561-8457-6fdeed4f50a3', '-A 1:set:2', persistent) # part2 offset 2MB size 1.5MB - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2', '--partition-guid=2:cc9c6e4a-6551-4cb5-87be-3210f96c86fb', persistent) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) cmd = ('sgdisk', '--load-backup=' + persistent) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) cmd = ('cp', persistent, self.path) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) @pytest.fixture(scope='function') def state_disk_image(ubman): diff --git a/test/py/tests/test_kconfig.py b/test/py/tests/test_kconfig.py index 9aeffa748c4..b4a28ec7a5a 100644 --- a/test/py/tests/test_kconfig.py +++ b/test/py/tests/test_kconfig.py @@ -4,7 +4,7 @@ import pytest -import u_boot_utils as util +import utils as util # This is needed for Azure, since the default '..' directory is not writeable TMPDIR = '/tmp/test_kconfig' diff --git a/test/py/tests/test_md.py b/test/py/tests/test_md.py index 69e12eb625f..5c7bcbd420b 100644 --- a/test/py/tests/test_md.py +++ b/test/py/tests/test_md.py @@ -3,14 +3,14 @@ # Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. import pytest -import u_boot_utils +import utils @pytest.mark.buildconfigspec('cmd_memory') def test_md(ubman): """Test that md reads memory as expected, and that memory can be modified using the mw command.""" - ram_base = u_boot_utils.find_ram_base(ubman) + ram_base = utils.find_ram_base(ubman) addr = '%08x' % ram_base val = 'a5f09876' expected_response = addr + ': ' + val @@ -26,7 +26,7 @@ def test_md_repeat(ubman): """Test command repeat (via executing an empty command) operates correctly for "md"; the command must repeat and dump an incrementing address.""" - ram_base = u_boot_utils.find_ram_base(ubman) + ram_base = utils.find_ram_base(ubman) addr_base = '%08x' % ram_base words = 0x10 addr_repeat = '%08x' % (ram_base + (words * 4)) diff --git a/test/py/tests/test_mmc.py b/test/py/tests/test_mmc.py index 4ecd999c02c..4916dcd8529 100644 --- a/test/py/tests/test_mmc.py +++ b/test/py/tests/test_mmc.py @@ -4,7 +4,7 @@ import pytest import random import re -import u_boot_utils +import utils """ Note: This test doesn't rely on boardenv_* configuration values but it can @@ -290,7 +290,7 @@ def test_mmc_fatload_fatwrite(ubman): for y in mmc_modes: ubman.run_command('mmc dev %d %d %d' % x, part, y) part_detect = 1 - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) devices[x]['addr_%d' % part] = addr size = random.randint(4, 1 * 1024 * 1024) devices[x]['size_%d' % part] = size @@ -394,7 +394,7 @@ def test_mmc_ext4load_ext4write(ubman): for y in mmc_modes: ubman.run_command('mmc dev %d %d %d' % x, part, y) part_detect = 1 - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) devices[x]['addr_%d' % part] = addr size = random.randint(4, 1 * 1024 * 1024) devices[x]['size_%d' % part] = size @@ -658,7 +658,7 @@ def test_mmc_fat_read_write_files(ubman): for y in mmc_modes: ubman.run_command('mmc dev %d %d %d' % x, part, y) part_detect = 1 - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) count_f = 0 addr_l = [] size_l = [] diff --git a/test/py/tests/test_mmc_rd.py b/test/py/tests/test_mmc_rd.py index 3c8356f872f..cd1e299aa9d 100644 --- a/test/py/tests/test_mmc_rd.py +++ b/test/py/tests/test_mmc_rd.py @@ -7,7 +7,7 @@ import pytest import time -import u_boot_utils +import utils """ This test relies on boardenv_* to containing configuration values to define @@ -241,7 +241,7 @@ def test_mmc_rd(ubman, env__mmc_rd_config): bcfg = ubman.config.buildconfig has_cmd_memory = bcfg.get('config_cmd_memory', 'n') == 'y' has_cmd_crc32 = bcfg.get('config_cmd_crc32', 'n') == 'y' - ram_base = u_boot_utils.find_ram_base(ubman) + ram_base = utils.find_ram_base(ubman) addr = '0x%08x' % ram_base # Select MMC device diff --git a/test/py/tests/test_mmc_wr.py b/test/py/tests/test_mmc_wr.py index 533bae04fd2..41a75f885e1 100644 --- a/test/py/tests/test_mmc_wr.py +++ b/test/py/tests/test_mmc_wr.py @@ -6,7 +6,7 @@ # to the eMMC or SD card, then reads it back and performs a comparison. import pytest -import u_boot_utils +import utils """ This test relies on boardenv_* to containing configuration values to define @@ -61,7 +61,7 @@ def test_mmc_wr(ubman, env__mmc_wr_config): count_bytes = count_sectors * 512 bcfg = ubman.config.buildconfig - ram_base = u_boot_utils.find_ram_base(ubman) + ram_base = utils.find_ram_base(ubman) src_addr = '0x%08x' % ram_base dst_addr = '0x%08x' % (ram_base + count_bytes) diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py index 52ecf93d41d..9f4ee0c9ed4 100644 --- a/test/py/tests/test_net.py +++ b/test/py/tests/test_net.py @@ -5,7 +5,7 @@ # tftpboot commands. import pytest -import u_boot_utils +import utils import uuid import datetime import re @@ -315,7 +315,7 @@ def test_net_nfs(ubman): addr = f.get('addr', None) if not addr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) fn = f['fn'] output = ubman.run_command('nfs %x %s' % (addr, fn)) @@ -411,7 +411,7 @@ def test_net_tftpput(ubman): addr = f.get("addr", None) if not addr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) sz = f.get("size", None) timeout = f.get("timeout", ubman.p.timeout) diff --git a/test/py/tests/test_net_boot.py b/test/py/tests/test_net_boot.py index d0230808b9f..abf6dfbaf5e 100644 --- a/test/py/tests/test_net_boot.py +++ b/test/py/tests/test_net_boot.py @@ -2,7 +2,7 @@ # (C) Copyright 2023, Advanced Micro Devices, Inc. import pytest -import u_boot_utils +import utils import test_net import re @@ -130,7 +130,7 @@ def setup_tftpboot_boot(ubman): setup_networking(ubman) addr = f.get('addr', None) if not addr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) fn = f['fn'] timeout = f.get('timeout', 50000) diff --git a/test/py/tests/test_of_migrate.py b/test/py/tests/test_of_migrate.py index 3b0fa2f871b..1692cbc48bb 100644 --- a/test/py/tests/test_of_migrate.py +++ b/test/py/tests/test_of_migrate.py @@ -7,7 +7,7 @@ import os import pytest -import u_boot_utils as util +import utils as util # This is needed for Azure, since the default '..' directory is not writeable TMPDIR1 = '/tmp/test_no_migrate' diff --git a/test/py/tests/test_ofplatdata.py b/test/py/tests/test_ofplatdata.py index 47d6ddc8a50..d414a910d9f 100644 --- a/test/py/tests/test_ofplatdata.py +++ b/test/py/tests/test_ofplatdata.py @@ -2,7 +2,7 @@ # Copyright (c) 2016 Google, Inc import pytest -import u_boot_utils as util +import utils as util @pytest.mark.boardspec('sandbox_spl') @pytest.mark.buildconfigspec('spl_of_platdata') diff --git a/test/py/tests/test_optee_rpmb.py b/test/py/tests/test_optee_rpmb.py index d20d4bc4828..1ef1c117d27 100644 --- a/test/py/tests/test_optee_rpmb.py +++ b/test/py/tests/test_optee_rpmb.py @@ -7,7 +7,7 @@ This tests optee_rpmb cmd in U-Boot """ import pytest -import u_boot_utils as util +import utils as util @pytest.mark.buildconfigspec('cmd_optee_rpmb') def test_optee_rpmb_read_write(ubman): diff --git a/test/py/tests/test_pinmux.py b/test/py/tests/test_pinmux.py index f8c3f0dfbef..ee79e843341 100644 --- a/test/py/tests/test_pinmux.py +++ b/test/py/tests/test_pinmux.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 import pytest -import u_boot_utils +import utils @pytest.mark.buildconfigspec('cmd_pinmux') def test_pinmux_usage_1(ubman): diff --git a/test/py/tests/test_pstore.py b/test/py/tests/test_pstore.py index 69b13fb0e4b..70e07503ad3 100644 --- a/test/py/tests/test_pstore.py +++ b/test/py/tests/test_pstore.py @@ -3,7 +3,7 @@ # Author: Frédéric Danis import pytest -import u_boot_utils +import utils import os import tempfile import shutil diff --git a/test/py/tests/test_sandbox_opts.py b/test/py/tests/test_sandbox_opts.py index a6dc394e554..16901409172 100644 --- a/test/py/tests/test_sandbox_opts.py +++ b/test/py/tests/test_sandbox_opts.py @@ -4,7 +4,7 @@ import pytest -import u_boot_utils as util +import utils as util # This is needed for Azure, since the default '..' directory is not writeable TMPDIR = '/tmp/test_cmdline' diff --git a/test/py/tests/test_scp03.py b/test/py/tests/test_scp03.py index 799754ac54b..296d7c7d953 100644 --- a/test/py/tests/test_scp03.py +++ b/test/py/tests/test_scp03.py @@ -11,7 +11,7 @@ For additional details check doc/usage/scp03.rst """ import pytest -import u_boot_utils as util +import utils as util @pytest.mark.buildconfigspec('cmd_scp03') def test_scp03(ubman): diff --git a/test/py/tests/test_sf.py b/test/py/tests/test_sf.py index 9c3b8927c0f..5b4ba80f18b 100644 --- a/test/py/tests/test_sf.py +++ b/test/py/tests/test_sf.py @@ -5,7 +5,7 @@ import re import pytest import random -import u_boot_utils +import utils """ Note: This test relies on boardenv_* containing configuration values to define @@ -57,7 +57,7 @@ def sf_prepare(ubman, env__sf_config): """ sf_params = {} - sf_params['ram_base'] = u_boot_utils.find_ram_base(ubman) + sf_params['ram_base'] = utils.find_ram_base(ubman) probe_id = env__sf_config.get('id', 0) speed = env__sf_config.get('speed', 0) @@ -123,14 +123,14 @@ def sf_read(ubman, env__sf_config, sf_params): cmd = 'mw.b %08x %02x %x' % (addr, pattern, count) ubman.run_command(cmd) - crc_pattern = u_boot_utils.crc32(ubman, addr, count) + crc_pattern = utils.crc32(ubman, addr, count) if crc_expected: assert crc_pattern != crc_expected cmd = 'sf read %08x %08x %x' % (addr, offset, count) response = ubman.run_command(cmd) assert 'Read: OK' in response, 'Read operation failed' - crc_readback = u_boot_utils.crc32(ubman, addr, count) + crc_readback = utils.crc32(ubman, addr, count) assert crc_pattern != crc_readback, 'sf read did not update RAM content.' if crc_expected: assert crc_readback == crc_expected @@ -156,7 +156,7 @@ def sf_update(ubman, env__sf_config, sf_params): cmd = 'mw.b %08x %02x %x' % (addr, pattern, count) ubman.run_command(cmd) - crc_pattern = u_boot_utils.crc32(ubman, addr, count) + crc_pattern = utils.crc32(ubman, addr, count) cmd = 'sf update %08x %08x %x' % (addr, offset, count) ubman.run_command(cmd) @@ -201,7 +201,7 @@ def test_sf_erase(ubman, env__sf_config): cmd = 'mw.b %08x ff %x' % (addr, count) ubman.run_command(cmd) - crc_ffs = u_boot_utils.crc32(ubman, addr, count) + crc_ffs = utils.crc32(ubman, addr, count) crc_read = sf_read(ubman, env__sf_config, sf_params) assert crc_ffs == crc_read, 'Unexpected CRC32 after erase operation.' diff --git a/test/py/tests/test_source.py b/test/py/tests/test_source.py index 30160d06dc6..60013e438ba 100644 --- a/test/py/tests/test_source.py +++ b/test/py/tests/test_source.py @@ -3,7 +3,7 @@ import os import pytest -import u_boot_utils as util +import utils as util @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_echo') diff --git a/test/py/tests/test_spi.py b/test/py/tests/test_spi.py index 5e61ef1162d..dd767528dbf 100644 --- a/test/py/tests/test_spi.py +++ b/test/py/tests/test_spi.py @@ -51,7 +51,7 @@ env__spi_lock_unlock = { import random import re import pytest -import u_boot_utils +import utils SPI_DATA = {} EXPECTED_ERASE = 'Erased: OK' @@ -198,7 +198,7 @@ def test_spi_erase_block(ubman): def spi_write_twice(ubman, page_size, erase_size, total_size, timeout): ''' Random write till page size, random till size and full size ''' - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) old_size = 0 for size in ( @@ -271,7 +271,7 @@ def test_spi_write_twice(ubman): def spi_write_continues(ubman, page_size, erase_size, total_size, timeout): ''' Write with random size of data to continue SPI write case ''' spi_erase_block(ubman, erase_size, total_size) - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) output = ubman.run_command(f'crc32 {hex(addr + 0x10000)} {hex(total_size)}') m = re.search('==> (.+?)$', output) @@ -327,7 +327,7 @@ def spi_read_twice(ubman, page_size, total_size, timeout): ''' Read the whole SPI flash twice, random_size till full flash size, random till page size ''' for size in random.randint(4, page_size), random.randint(4, total_size), total_size: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) size = size & ~3 with ubman.temporary_timeout(timeout): output = ubman.run_command( @@ -451,13 +451,13 @@ def protect_ops(ubman, lock_addr, lock_size, ops="unlock"): def erase_write_ops(ubman, start, size): ''' Basic erase and write operation for flash ''' - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) flash_ops(ubman, 'erase', start, size, 0, 0, EXPECTED_ERASE) flash_ops(ubman, 'write', start, size, addr, 0, EXPECTED_WRITE) def spi_lock_unlock(ubman, lock_addr, lock_size): ''' Lock unlock operations for SPI family flash ''' - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) erase_size = get_erase_size() # Find the protected/un-protected region @@ -612,7 +612,7 @@ def test_spi_negative(ubman): total_size = get_total_size() erase_size = get_erase_size() page_size = get_page_size() - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) i = 0 while i < loop: # Erase negative test diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py index 47e0e7a1b6d..ade102a387e 100644 --- a/test/py/tests/test_tpm2.py +++ b/test/py/tests/test_tpm2.py @@ -4,7 +4,7 @@ import os.path import pytest -import u_boot_utils +import utils import re import time @@ -197,7 +197,7 @@ def test_tpm2_get_capability(ubman): tpm2_sandbox_init(ubman) force_init(ubman) - ram = u_boot_utils.find_ram_base(ubman) + ram = utils.find_ram_base(ubman) read_cap = ubman.run_command('tpm2 get_capability 0x6 0x20e 0x200 1') #0x%x 1' % ram) output = ubman.run_command('echo $?') @@ -220,7 +220,7 @@ def test_tpm2_dam_parameters(ubman): if is_sandbox(ubman): tpm2_sandbox_init(ubman) force_init(ubman) - ram = u_boot_utils.find_ram_base(ubman) + ram = utils.find_ram_base(ubman) # Set the DAM parameters to known values ubman.run_command('tpm2 dam_parameters 3 10 0') @@ -245,7 +245,7 @@ def test_tpm2_pcr_read(ubman): tpm2_sandbox_init(ubman) force_init(ubman) - ram = u_boot_utils.find_ram_base(ubman) + ram = utils.find_ram_base(ubman) read_pcr = ubman.run_command('tpm2 pcr_read 10 0x%x' % ram) output = ubman.run_command('echo $?') @@ -273,7 +273,7 @@ def test_tpm2_pcr_extend(ubman): if is_sandbox(ubman): tpm2_sandbox_init(ubman) force_init(ubman) - ram = u_boot_utils.find_ram_base(ubman) + ram = utils.find_ram_base(ubman) read_pcr = ubman.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = ubman.run_command('echo $?') diff --git a/test/py/tests/test_trace.py b/test/py/tests/test_trace.py index d008f688571..6fa4229233b 100644 --- a/test/py/tests/test_trace.py +++ b/test/py/tests/test_trace.py @@ -6,7 +6,7 @@ import os import pytest import re -import u_boot_utils as util +import utils as util # This is needed for Azure, since the default '..' directory is not writeable TMPDIR = '/tmp/test_trace' diff --git a/test/py/tests/test_ums.py b/test/py/tests/test_ums.py index fa13a393fc6..caf6c0a7270 100644 --- a/test/py/tests/test_ums.py +++ b/test/py/tests/test_ums.py @@ -11,7 +11,7 @@ import os.path import pytest import re import time -import u_boot_utils +import utils """ Note: This test relies on: @@ -113,8 +113,7 @@ def test_ums(ubman, env__usb_dev_port, env__block_devs): mount_subdir = env__block_devs[0]['writable_fs_subdir'] part_num = env__block_devs[0]['writable_fs_partition'] host_ums_part_node = '%s-part%d' % (host_ums_dev_node, part_num) - test_f = u_boot_utils.PersistentRandomFile(ubman, 'ums.bin', - 1024 * 1024); + test_f = utils.PersistentRandomFile(ubman, 'ums.bin', 1024 * 1024); mounted_test_fn = mount_point + '/' + mount_subdir + test_f.fn else: host_ums_part_node = host_ums_dev_node @@ -136,7 +135,7 @@ def test_ums(ubman, env__usb_dev_port, env__block_devs): cmd = 'ums %s %s %s' % (tgt_usb_ctlr, tgt_dev_type, tgt_dev_id) ubman.run_command(cmd, wait_for_prompt=False) ubman.wait_for(re.compile('UMS: LUN.*[\r\n]')) - fh = u_boot_utils.wait_until_open_succeeds(host_ums_part_node) + fh = utils.wait_until_open_succeeds(host_ums_part_node) ubman.log.action('Reading raw data from UMS device') fh.read(4096) fh.close() @@ -153,7 +152,7 @@ def test_ums(ubman, env__usb_dev_port, env__block_devs): ubman.log.action('Mounting exported UMS device') cmd = ('/bin/mount', host_ums_part_node) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) def umount(ignore_errors): """Unmount the block device that U-Boot exports. @@ -170,7 +169,7 @@ def test_ums(ubman, env__usb_dev_port, env__block_devs): ubman.log.action('Unmounting UMS device') cmd = ('/bin/umount', host_ums_part_node) - u_boot_utils.run_and_log(ubman, cmd, ignore_errors) + utils.run_and_log(ubman, cmd, ignore_errors) def stop_ums(ignore_errors): """Stop U-Boot's ums shell command from executing. @@ -191,7 +190,7 @@ def test_ums(ubman, env__usb_dev_port, env__block_devs): ubman.log.action( 'Stopping long-running U-Boot ums shell command') ubman.ctrlc() - u_boot_utils.wait_until_file_open_fails(host_ums_part_node, + utils.wait_until_file_open_fails(host_ums_part_node, ignore_errors) ignore_cleanup_errors = True @@ -202,11 +201,11 @@ def test_ums(ubman, env__usb_dev_port, env__block_devs): mount() ubman.log.action('Writing test file via UMS') cmd = ('rm', '-f', mounted_test_fn) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) if os.path.exists(mounted_test_fn): raise Exception('Could not rm target UMS test file') cmd = ('cp', test_f.abs_fn, mounted_test_fn) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) ignore_cleanup_errors = False finally: umount(ignore_errors=ignore_cleanup_errors) @@ -219,9 +218,9 @@ def test_ums(ubman, env__usb_dev_port, env__block_devs): try: mount() ubman.log.action('Reading test file back via UMS') - read_back_hash = u_boot_utils.md5sum_file(mounted_test_fn) + read_back_hash = utils.md5sum_file(mounted_test_fn) cmd = ('rm', '-f', mounted_test_fn) - u_boot_utils.run_and_log(ubman, cmd) + utils.run_and_log(ubman, cmd) ignore_cleanup_errors = False finally: umount(ignore_errors=ignore_cleanup_errors) diff --git a/test/py/tests/test_upl.py b/test/py/tests/test_upl.py index ca06dffd0bf..c8eeaa024e5 100644 --- a/test/py/tests/test_upl.py +++ b/test/py/tests/test_upl.py @@ -6,7 +6,7 @@ import os import pytest -import u_boot_utils +import utils @pytest.mark.boardspec('sandbox_vpl') def test_upl_handoff(ubman): diff --git a/test/py/tests/test_usb.py b/test/py/tests/test_usb.py index 6247f9211df..1dcd0834f55 100644 --- a/test/py/tests/test_usb.py +++ b/test/py/tests/test_usb.py @@ -4,7 +4,7 @@ import pytest import random import re -import u_boot_utils +import utils """ Note: This test doesn't rely on boardenv_* configuration values but it can @@ -296,7 +296,7 @@ def test_usb_fatls_fatinfo(ubman): pytest.skip('No %s partition detected' % fs.upper()) def usb_fatload_fatwrite(ubman, fs, x, part): - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) size = random.randint(4, 1 * 1024 * 1024) output = ubman.run_command('crc32 %x %x' % (addr, size)) m = re.search('==> (.+?)', output) @@ -391,7 +391,7 @@ def test_usb_ext4ls(ubman): pytest.skip('No %s partition detected' % fs.upper()) def usb_ext4load_ext4write(ubman, fs, x, part): - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) size = random.randint(4, 1 * 1024 * 1024) output = ubman.run_command('crc32 %x %x' % (addr, size)) m = re.search('==> (.+?)', output) @@ -505,7 +505,7 @@ def test_usb_ext2load(ubman): part_detect = 1 file, size, expected_crc32 = \ usb_ext4load_ext4write(ubman, fs, x, part) - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) offset = random.randrange(128, 1024, 128) output = ubman.run_command( @@ -572,7 +572,7 @@ def test_usb_load(ubman): for part in partitions: part_detect = 1 - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) if fs == 'fat': file, size, expected_crc32 = \ @@ -618,7 +618,7 @@ def test_usb_save(ubman): for part in partitions: part_detect = 1 - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) size = random.randint(4, 1 * 1024 * 1024) file = '%s_%d' % ('uboot_test', size) diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 3bcdc7ac954..d7cf95d461b 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -13,7 +13,7 @@ import os import os.path import pytest -import u_boot_utils +import utils # pylint: disable=E0611 from tests import fs_helper from test_android import test_abootimg @@ -52,8 +52,8 @@ def setup_image(cons, devnum, part_type, img_size=20, second_part=False, if second_part: spec += '\ntype=c' - u_boot_utils.run_and_log(cons, f'qemu-img create {fname} 20M') - u_boot_utils.run_and_log(cons, f'sfdisk {fname}', + utils.run_and_log(cons, f'qemu-img create {fname} 20M') + utils.run_and_log(cons, f'sfdisk {fname}', stdin=spec.encode('utf-8')) return fname, mnt @@ -149,12 +149,12 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} infname = os.path.join(cons.config.source_dir, 'test/py/tests/bootstd/armbian.bmp.xz') bmp_file = os.path.join(bootdir, 'boot.bmp') - u_boot_utils.run_and_log( + utils.run_and_log( cons, ['sh', '-c', f'xz -dc {infname} >{bmp_file}']) mkimage = cons.config.build_dir + '/tools/mkimage' - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'{mkimage} -C none -A arm -T script -d {cmd_fname} {scr_fname}') kernel = 'vmlinuz-5.15.63-rockchip64' @@ -165,16 +165,16 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} symlink = os.path.join(bootdir, 'Image') if os.path.exists(symlink): os.remove(symlink) - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'echo here {kernel} {symlink}') os.symlink(kernel, symlink) fsfile = 'ext18M.img' - u_boot_utils.run_and_log(cons, f'fallocate -l 18M {fsfile}') - u_boot_utils.run_and_log(cons, f'mkfs.ext4 {fsfile} -d {mnt}') - u_boot_utils.run_and_log(cons, f'dd if={fsfile} of={fname} bs=1M seek=1') - u_boot_utils.run_and_log(cons, f'rm -rf {mnt}') - u_boot_utils.run_and_log(cons, f'rm -f {fsfile}') + utils.run_and_log(cons, f'fallocate -l 18M {fsfile}') + utils.run_and_log(cons, f'mkfs.ext4 {fsfile} -d {mnt}') + utils.run_and_log(cons, f'dd if={fsfile} of={fname} bs=1M seek=1') + utils.run_and_log(cons, f'rm -rf {mnt}') + utils.run_and_log(cons, f'rm -f {fsfile}') def setup_bootflow_image(cons): """Create a 20MB disk image with a single FAT partition""" @@ -208,7 +208,7 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) with open(inf, 'wb') as fd: fd.write(gzip.compress(b'vmlinux')) mkimage = cons.config.build_dir + '/tools/mkimage' - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'{mkimage} -f auto -d {inf} {os.path.join(mnt, vmlinux)}') with open(os.path.join(mnt, initrd), 'w', encoding='ascii') as fd: @@ -217,16 +217,16 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) mkdir_cond(os.path.join(mnt, dtbdir)) dtb_file = os.path.join(mnt, f'{dtbdir}/sandbox.dtb') - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'dtc -o {dtb_file}', stdin=b'/dts-v1/; / {};') fsfile = 'vfat18M.img' - u_boot_utils.run_and_log(cons, f'fallocate -l 18M {fsfile}') - u_boot_utils.run_and_log(cons, f'mkfs.vfat {fsfile}') - u_boot_utils.run_and_log(cons, ['sh', '-c', f'mcopy -i {fsfile} {mnt}/* ::/']) - u_boot_utils.run_and_log(cons, f'dd if={fsfile} of={fname} bs=1M seek=1') - u_boot_utils.run_and_log(cons, f'rm -rf {mnt}') - u_boot_utils.run_and_log(cons, f'rm -f {fsfile}') + utils.run_and_log(cons, f'fallocate -l 18M {fsfile}') + utils.run_and_log(cons, f'mkfs.vfat {fsfile}') + utils.run_and_log(cons, ['sh', '-c', f'mcopy -i {fsfile} {mnt}/* ::/']) + utils.run_and_log(cons, f'dd if={fsfile} of={fname} bs=1M seek=1') + utils.run_and_log(cons, f'rm -rf {mnt}') + utils.run_and_log(cons, f'rm -f {fsfile}') def setup_cros_image(cons): """Create a 20MB disk image with ChromiumOS partitions""" @@ -248,7 +248,7 @@ def setup_cros_image(cons): """ kern_part = os.path.join(cons.config.result_dir, f'kern-part-{arch}.bin') - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'futility vbutil_kernel --pack {kern_part} ' '--keyblock doc/chromium/files/devkeys/kernel.keyblock ' @@ -276,8 +276,8 @@ def setup_cros_image(cons): mmc_dev = 5 fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') - u_boot_utils.run_and_log(cons, f'qemu-img create {fname} 20M') - u_boot_utils.run_and_log(cons, f'cgpt create {fname}') + utils.run_and_log(cons, f'qemu-img create {fname} 20M') + utils.run_and_log(cons, f'cgpt create {fname}') uuid_state = 'ebd0a0a2-b9e5-4433-87c0-68b6b72699c7' uuid_kern = 'fe3a2a5d-4f32-41a7-b725-accc3285a309' @@ -316,13 +316,13 @@ def setup_cros_image(cons): size = int(size_str[:-1]) * sect_1mb else: size = int(size_str) - u_boot_utils.run_and_log( + utils.run_and_log( cons, f"cgpt add -i {part['num']} -b {ptr} -s {size} -t {part['type']} {fname}") ptr += size - u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}') - out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}') + utils.run_and_log(cons, f'cgpt boot -p {fname}') + out = utils.run_and_log(cons, f'cgpt show -q {fname}') # We expect something like this: # 8239 2048 1 Basic data @@ -389,8 +389,8 @@ def setup_android_image(cons): mmc_dev = 7 fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') - u_boot_utils.run_and_log(cons, f'qemu-img create {fname} 20M') - u_boot_utils.run_and_log(cons, f'cgpt create {fname}') + utils.run_and_log(cons, f'qemu-img create {fname} 20M') + utils.run_and_log(cons, f'cgpt create {fname}') ptr = 40 @@ -412,13 +412,13 @@ def setup_android_image(cons): size = int(size_str[:-1]) * sect_1mb else: size = int(size_str) - u_boot_utils.run_and_log( + utils.run_and_log( cons, f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}") ptr += size - u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}') - out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}') + utils.run_and_log(cons, f'cgpt boot -p {fname}') + out = utils.run_and_log(cons, f'cgpt show -q {fname}') # Create a dict (indexed by partition number) containing the above info for line in out.splitlines(): @@ -445,8 +445,8 @@ def setup_android_image(cons): mmc_dev = 8 fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') - u_boot_utils.run_and_log(cons, f'qemu-img create {fname} 20M') - u_boot_utils.run_and_log(cons, f'cgpt create {fname}') + utils.run_and_log(cons, f'qemu-img create {fname} 20M') + utils.run_and_log(cons, f'cgpt create {fname}') ptr = 40 @@ -466,13 +466,13 @@ def setup_android_image(cons): size = int(size_str[:-1]) * sect_1mb else: size = int(size_str) - u_boot_utils.run_and_log( + utils.run_and_log( cons, f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}") ptr += size - u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}') - out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}') + utils.run_and_log(cons, f'cgpt boot -p {fname}') + out = utils.run_and_log(cons, f'cgpt show -q {fname}') # Create a dict (indexed by partition number) containing the above info for line in out.splitlines(): @@ -502,7 +502,7 @@ def setup_cedit_file(cons): 'test/boot/files/expo_ids.h') expo_tool = os.path.join(cons.config.source_dir, 'tools/expo.py') outfname = 'cedit.dtb' - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'{expo_tool} -e {inhname} -l {infname} -o {outfname}') @pytest.mark.buildconfigspec('ut_dm') @@ -528,7 +528,7 @@ def test_ut_dm_init(ubman): data = b'\x00' * (2 * 1024 * 1024) with open(fn, 'wb') as fh: fh.write(data) - u_boot_utils.run_and_log( + utils.run_and_log( ubman, f'sfdisk {fn}', stdin=b'type=83') fs_helper.mk_fs(ubman.config, 'ext2', 0x200000, '2MB', None) @@ -559,12 +559,12 @@ def setup_efi_image(cons): with open(efi_dst, 'wb') as outf: outf.write(inf.read()) fsfile = 'vfat18M.img' - u_boot_utils.run_and_log(cons, f'fallocate -l 18M {fsfile}') - u_boot_utils.run_and_log(cons, f'mkfs.vfat {fsfile}') - u_boot_utils.run_and_log(cons, ['sh', '-c', f'mcopy -vs -i {fsfile} {mnt}/* ::/']) - u_boot_utils.run_and_log(cons, f'dd if={fsfile} of={fname} bs=1M seek=1') - u_boot_utils.run_and_log(cons, f'rm -rf {mnt}') - u_boot_utils.run_and_log(cons, f'rm -f {fsfile}') + utils.run_and_log(cons, f'fallocate -l 18M {fsfile}') + utils.run_and_log(cons, f'mkfs.vfat {fsfile}') + utils.run_and_log(cons, ['sh', '-c', f'mcopy -vs -i {fsfile} {mnt}/* ::/']) + utils.run_and_log(cons, f'dd if={fsfile} of={fname} bs=1M seek=1') + utils.run_and_log(cons, f'rm -rf {mnt}') + utils.run_and_log(cons, f'rm -f {fsfile}') @pytest.mark.buildconfigspec('cmd_bootflow') @pytest.mark.buildconfigspec('sandbox') diff --git a/test/py/tests/test_vbe_vpl.py b/test/py/tests/test_vbe_vpl.py index 11389176335..317a324281e 100644 --- a/test/py/tests/test_vbe_vpl.py +++ b/test/py/tests/test_vbe_vpl.py @@ -6,7 +6,7 @@ import os import pytest -import u_boot_utils +import utils @pytest.mark.boardspec('sandbox_vpl') @pytest.mark.requiredtool('dtc') @@ -19,13 +19,13 @@ def test_vbe_vpl(ubman): # Enable firmware1 and the mmc that it uses. These are needed for the full # VBE flow. - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'fdtput -t s {fdt} /bootstd/firmware0 status disabled') - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'fdtput -t s {fdt} /bootstd/firmware1 status okay') - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'fdtput -t s {fdt} /mmc3 status okay') - u_boot_utils.run_and_log( + utils.run_and_log( cons, f'fdtput -t s {fdt} /mmc3 filename {image_fname}') # Remove any existing RAM file, so we don't have old data present diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py index 724833dc976..691c6e6b839 100644 --- a/test/py/tests/test_vboot.py +++ b/test/py/tests/test_vboot.py @@ -42,7 +42,7 @@ import os import shutil import struct import pytest -import u_boot_utils as util +import utils as util import vboot_forge import vboot_evil diff --git a/test/py/tests/test_zynq_secure.py b/test/py/tests/test_zynq_secure.py index 0261d62a307..f066a03b182 100644 --- a/test/py/tests/test_zynq_secure.py +++ b/test/py/tests/test_zynq_secure.py @@ -3,7 +3,7 @@ import pytest import re -import u_boot_utils +import utils import test_net """ @@ -68,7 +68,7 @@ def test_zynq_aes_image(ubman): srcaddr = f.get('srcaddr', None) if not srcaddr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' fn = f['fn'] @@ -96,7 +96,7 @@ def test_zynq_aes_bitstream(ubman): srcaddr = f.get('srcaddr', None) if not srcaddr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' fn = f['fnbit'] @@ -124,7 +124,7 @@ def test_zynq_aes_partial_bitstream(ubman): srcaddr = f.get('srcaddr', None) if not srcaddr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' fn = f['fnpbit'] @@ -150,7 +150,7 @@ def test_zynq_rsa_image(ubman): srcaddr = f.get('srcaddr', None) if not srcaddr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' fn = f['fn'] @@ -176,7 +176,7 @@ def test_zynq_rsa_image_invalid(ubman): srcaddr = f.get('srcaddr', None) if not srcaddr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' fninvalid = f['fninvalid'] diff --git a/test/py/tests/test_zynqmp_secure.py b/test/py/tests/test_zynqmp_secure.py index 7549e2cc39f..c057e36383f 100644 --- a/test/py/tests/test_zynqmp_secure.py +++ b/test/py/tests/test_zynqmp_secure.py @@ -3,7 +3,7 @@ import pytest import re -import u_boot_utils +import utils import test_net """ @@ -45,7 +45,7 @@ def test_zynqmp_secure_boot_image(ubman): addr = f.get('addr', None) if not addr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' fn = f['fn'] @@ -78,7 +78,7 @@ def test_zynqmp_secure_boot_img_kup(ubman): keyaddr = f.get('keyaddr', None) if not keyaddr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' keyfn = f['keyfn'] output = ubman.run_command('tftpboot %x %s' % (keyaddr, keyfn)) @@ -86,7 +86,7 @@ def test_zynqmp_secure_boot_img_kup(ubman): addr = f.get('addr', None) if not addr: - addr = u_boot_utils.find_ram_base(ubman) + addr = utils.find_ram_base(ubman) expected_tftp = 'Bytes transferred = ' fn = f['enckupfn'] output = ubman.run_command('tftpboot %x %s' % (addr, fn)) diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py deleted file mode 100644 index 7eaceb39d9d..00000000000 --- a/test/py/u_boot_console_base.py +++ /dev/null @@ -1,613 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Copyright (c) 2015 Stephen Warren -# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. - -# Common logic to interact with U-Boot via the console. This class provides -# the interface that tests use to execute U-Boot shell commands and wait for -# their results. Sub-classes exist to perform board-type-specific setup -# operations, such as spawning a sub-process for Sandbox, or attaching to the -# serial console of real hardware. - -import multiplexed_log -import os -import pytest -import re -import sys -import u_boot_spawn -from u_boot_spawn import BootFail, Timeout, Unexpected, handle_exception - -# Regexes for text we expect U-Boot to send to the console. -pattern_u_boot_spl_signon = re.compile('(U-Boot SPL \\d{4}\\.\\d{2}[^\r\n]*\\))') -pattern_u_boot_main_signon = re.compile('(U-Boot \\d{4}\\.\\d{2}[^\r\n]*\\))') -pattern_stop_autoboot_prompt = re.compile('Hit any key to stop autoboot: ') -pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'') -pattern_error_notification = re.compile('## Error: ') -pattern_error_please_reset = re.compile('### ERROR ### Please RESET the board ###') -pattern_ready_prompt = re.compile('{lab ready in (.*)s: (.*)}') -pattern_lab_mode = re.compile('{lab mode.*}') - -PAT_ID = 0 -PAT_RE = 1 - -# Timeout before expecting the console to be ready (in milliseconds) -TIMEOUT_MS = 30000 # Standard timeout -TIMEOUT_CMD_MS = 10000 # Command-echo timeout - -# Timeout for board preparation in lab mode. This needs to be enough to build -# U-Boot, write it to the board and then boot the board. Since this process is -# under the control of another program (e.g. Labgrid), it will failure sooner -# if something goes way. So use a very long timeout here to cover all possible -# situations. -TIMEOUT_PREPARE_MS = 3 * 60 * 1000 - -bad_pattern_defs = ( - ('spl_signon', pattern_u_boot_spl_signon), - ('main_signon', pattern_u_boot_main_signon), - ('stop_autoboot_prompt', pattern_stop_autoboot_prompt), - ('unknown_command', pattern_unknown_command), - ('error_notification', pattern_error_notification), - ('error_please_reset', pattern_error_please_reset), -) - -class ConsoleDisableCheck(object): - """Context manager (for Python's with statement) that temporarily disables - the specified console output error check. This is useful when deliberately - executing a command that is known to trigger one of the error checks, in - order to test that the error condition is actually raised. This class is - used internally by ConsoleBase::disable_check(); it is not intended for - direct usage.""" - - def __init__(self, console, check_type): - self.console = console - self.check_type = check_type - - def __enter__(self): - self.console.disable_check_count[self.check_type] += 1 - self.console.eval_bad_patterns() - - def __exit__(self, extype, value, traceback): - self.console.disable_check_count[self.check_type] -= 1 - self.console.eval_bad_patterns() - -class ConsoleEnableCheck(object): - """Context manager (for Python's with statement) that temporarily enables - the specified console output error check. This is useful when executing a - command that might raise an extra bad pattern, beyond the default bad - patterns, in order to validate that the extra bad pattern is actually - detected. This class is used internally by ConsoleBase::enable_check(); it - is not intended for direct usage.""" - - def __init__(self, console, check_type, check_pattern): - self.console = console - self.check_type = check_type - self.check_pattern = check_pattern - - def __enter__(self): - global bad_pattern_defs - self.default_bad_patterns = bad_pattern_defs - bad_pattern_defs += ((self.check_type, self.check_pattern),) - self.console.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs} - self.console.eval_bad_patterns() - - def __exit__(self, extype, value, traceback): - global bad_pattern_defs - bad_pattern_defs = self.default_bad_patterns - self.console.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs} - self.console.eval_bad_patterns() - -class ConsoleSetupTimeout(object): - """Context manager (for Python's with statement) that temporarily sets up - timeout for specific command. This is useful when execution time is greater - then default 30s.""" - - def __init__(self, console, timeout): - self.p = console.p - self.orig_timeout = self.p.timeout - self.p.timeout = timeout - - def __enter__(self): - return self - - def __exit__(self, extype, value, traceback): - self.p.timeout = self.orig_timeout - -class ConsoleBase(object): - """The interface through which test functions interact with the U-Boot - console. This primarily involves executing shell commands, capturing their - results, and checking for common error conditions. Some common utilities - are also provided too.""" - - def __init__(self, log, config, max_fifo_fill): - """Initialize a U-Boot console connection. - - Can only usefully be called by sub-classes. - - Args: - log: A multiplexed_log.Logfile object, to which the U-Boot output - will be logged. - config: A configuration data structure, as built by conftest.py. - max_fifo_fill: The maximum number of characters to send to U-Boot - command-line before waiting for U-Boot to echo the characters - back. For UART-based HW without HW flow control, this value - should be set less than the UART RX FIFO size to avoid - overflow, assuming that U-Boot can't keep up with full-rate - traffic at the baud rate. - - Returns: - Nothing. - """ - - self.log = log - self.config = config - self.max_fifo_fill = max_fifo_fill - - self.logstream = self.log.get_stream('console', sys.stdout) - - # Array slice removes leading/trailing quotes - self.prompt = self.config.buildconfig['config_sys_prompt'][1:-1] - self.prompt_compiled = re.compile('^' + re.escape(self.prompt), re.MULTILINE) - self.p = None - self.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs} - self.eval_bad_patterns() - - self.at_prompt = False - self.at_prompt_logevt = None - self.lab_mode = False - - def get_spawn(self): - # This is not called, ssubclass must define this. - # Return a value to avoid: - # u_boot_console_base.py:348:12: E1128: Assigning result of a function - # call, where the function returns None (assignment-from-none) - return u_boot_spawn.Spawn([]) - - - def eval_bad_patterns(self): - self.bad_patterns = [pat[PAT_RE] for pat in bad_pattern_defs \ - if self.disable_check_count[pat[PAT_ID]] == 0] - self.bad_pattern_ids = [pat[PAT_ID] for pat in bad_pattern_defs \ - if self.disable_check_count[pat[PAT_ID]] == 0] - - def close(self): - """Terminate the connection to the U-Boot console. - - This function is only useful once all interaction with U-Boot is - complete. Once this function is called, data cannot be sent to or - received from U-Boot. - - Args: - None. - - Returns: - Nothing. - """ - - if self.p: - self.log.start_section('Stopping U-Boot') - close_type = self.p.close() - self.log.info(f'Close type: {close_type}') - self.log.end_section('Stopping U-Boot') - self.logstream.close() - - def set_lab_mode(self): - """Select lab mode - - This tells us that we will get a 'lab ready' message when the board is - ready for use. We don't need to look for signon messages. - """ - self.log.info(f'test.py: Lab mode is active') - self.p.timeout = TIMEOUT_PREPARE_MS - self.lab_mode = True - - def wait_for_boot_prompt(self, loop_num = 1): - """Wait for the boot up until command prompt. This is for internal use only. - """ - try: - self.log.info('Waiting for U-Boot to be ready') - bcfg = self.config.buildconfig - config_spl_serial = bcfg.get('config_spl_serial', 'n') == 'y' - env_spl_skipped = self.config.env.get('env__spl_skipped', False) - env_spl_banner_times = self.config.env.get('env__spl_banner_times', 1) - - while not self.lab_mode and loop_num > 0: - loop_num -= 1 - while config_spl_serial and not env_spl_skipped and env_spl_banner_times > 0: - m = self.p.expect([pattern_u_boot_spl_signon, - pattern_lab_mode] + self.bad_patterns) - if m == 1: - self.set_lab_mode() - break - elif m != 0: - raise BootFail('Bad pattern found on SPL console: ' + - self.bad_pattern_ids[m - 1]) - env_spl_banner_times -= 1 - - if not self.lab_mode: - m = self.p.expect([pattern_u_boot_main_signon, - pattern_lab_mode] + self.bad_patterns) - if m == 1: - self.set_lab_mode() - elif m != 0: - raise BootFail('Bad pattern found on console: ' + - self.bad_pattern_ids[m - 1]) - if not self.lab_mode: - self.u_boot_version_string = self.p.after - while True: - m = self.p.expect([self.prompt_compiled, pattern_ready_prompt, - pattern_stop_autoboot_prompt] + self.bad_patterns) - if m == 0: - self.log.info(f'Found ready prompt {m}') - break - elif m == 1: - m = pattern_ready_prompt.search(self.p.after) - self.u_boot_version_string = m.group(2) - self.log.info(f'Lab: Board is ready') - self.p.timeout = TIMEOUT_MS - break - if m == 2: - self.log.info(f'Found autoboot prompt {m}') - self.p.send(' ') - continue - if not self.lab_mode: - raise BootFail('Missing prompt / ready message on console: ' + - self.bad_pattern_ids[m - 3]) - self.log.info(f'U-Boot is ready') - - finally: - self.log.timestamp() - - def run_command(self, cmd, wait_for_echo=True, send_nl=True, - wait_for_prompt=True, wait_for_reboot=False): - """Execute a command via the U-Boot console. - - The command is always sent to U-Boot. - - U-Boot echoes any command back to its output, and this function - typically waits for that to occur. The wait can be disabled by setting - wait_for_echo=False, which is useful e.g. when sending CTRL-C to - interrupt a long-running command such as "ums". - - Command execution is typically triggered by sending a newline - character. This can be disabled by setting send_nl=False, which is - also useful when sending CTRL-C. - - This function typically waits for the command to finish executing, and - returns the console output that it generated. This can be disabled by - setting wait_for_prompt=False, which is useful when invoking a long- - running command such as "ums". - - Args: - cmd: The command to send. - wait_for_echo: Boolean indicating whether to wait for U-Boot to - echo the command text back to its output. - send_nl: Boolean indicating whether to send a newline character - after the command string. - wait_for_prompt: Boolean indicating whether to wait for the - command prompt to be sent by U-Boot. This typically occurs - immediately after the command has been executed. - wait_for_reboot: Boolean indication whether to wait for the - reboot U-Boot. If this sets True, wait_for_prompt must also - be True. - - Returns: - If wait_for_prompt == False: - Nothing. - Else: - The output from U-Boot during command execution. In other - words, the text U-Boot emitted between the point it echod the - command string and emitted the subsequent command prompts. - """ - - if self.at_prompt and \ - self.at_prompt_logevt != self.logstream.logfile.cur_evt: - self.logstream.write(self.prompt, implicit=True) - - try: - self.at_prompt = False - if not self.p: - raise BootFail( - f"Lab failure: Connection lost when sending command '{cmd}'") - - if send_nl: - cmd += '\n' - rem = cmd # Remaining to be sent - with self.temporary_timeout(TIMEOUT_CMD_MS): - while rem: - # Limit max outstanding data, so UART FIFOs don't overflow - chunk = rem[:self.max_fifo_fill] - rem = rem[self.max_fifo_fill:] - self.p.send(chunk) - if not wait_for_echo: - continue - chunk = re.escape(chunk) - chunk = chunk.replace('\\\n', '[\r\n]') - m = self.p.expect([chunk] + self.bad_patterns) - if m != 0: - self.at_prompt = False - raise BootFail(f"Failed to get echo on console (cmd '{cmd}':rem '{rem}'): " + - self.bad_pattern_ids[m - 1]) - if not wait_for_prompt: - return - if wait_for_reboot: - self.wait_for_boot_prompt() - else: - m = self.p.expect([self.prompt_compiled] + self.bad_patterns) - if m != 0: - self.at_prompt = False - raise BootFail('Missing prompt on console: ' + - self.bad_pattern_ids[m - 1]) - self.at_prompt = True - self.at_prompt_logevt = self.logstream.logfile.cur_evt - # Only strip \r\n; space/TAB might be significant if testing - # indentation. - return self.p.before.strip('\r\n') - except Timeout as exc: - handle_exception(self.config, self, self.log, exc, - f"Lab failure: Timeout executing '{cmd}'", True) - raise - except BootFail as exc: - handle_exception(self.config, self, self.log, exc, - f"'Boot fail '{cmd}'", - True, self.get_spawn_output()) - raise - finally: - self.log.timestamp() - - def run_command_list(self, cmds): - """Run a list of commands. - - This is a helper function to call run_command() with default arguments - for each command in a list. - - Args: - cmd: List of commands (each a string). - Returns: - A list of output strings from each command, one element for each - command. - """ - output = [] - for cmd in cmds: - output.append(self.run_command(cmd)) - return output - - def ctrlc(self): - """Send a CTRL-C character to U-Boot. - - This is useful in order to stop execution of long-running synchronous - commands such as "ums". - - Args: - None. - - Returns: - Nothing. - """ - - self.log.action('Sending Ctrl-C') - self.run_command(chr(3), wait_for_echo=False, send_nl=False) - - def wait_for(self, text): - """Wait for a pattern to be emitted by U-Boot. - - This is useful when a long-running command such as "dfu" is executing, - and it periodically emits some text that should show up at a specific - location in the log file. - - Args: - text: The text to wait for; either a string (containing raw text, - not a regular expression) or an re object. - - Returns: - Nothing. - """ - - if type(text) == type(''): - text = re.escape(text) - m = self.p.expect([text] + self.bad_patterns) - if m != 0: - raise Unexpected( - "Unexpected pattern found on console (exp '{text}': " + - self.bad_pattern_ids[m - 1]) - - def drain_console(self): - """Read from and log the U-Boot console for a short time. - - U-Boot's console output is only logged when the test code actively - waits for U-Boot to emit specific data. There are cases where tests - can fail without doing this. For example, if a test asks U-Boot to - enable USB device mode, then polls until a host-side device node - exists. In such a case, it is useful to log U-Boot's console output - in case U-Boot printed clues as to why the host-side even did not - occur. This function will do that. - - Args: - None. - - Returns: - Nothing. - """ - - # If we are already not connected to U-Boot, there's nothing to drain. - # This should only happen when a previous call to run_command() or - # wait_for() failed (and hence the output has already been logged), or - # the system is shutting down. - if not self.p: - return - - orig_timeout = self.p.timeout - try: - # Drain the log for a relatively short time. - self.p.timeout = 1000 - # Wait for something U-Boot will likely never send. This will - # cause the console output to be read and logged. - self.p.expect(['This should never match U-Boot output']) - except: - # We expect a timeout, since U-Boot won't print what we waited - # for. Squash it when it happens. - # - # Squash any other exception too. This function is only used to - # drain (and log) the U-Boot console output after a failed test. - # The U-Boot process will be restarted, or target board reset, once - # this function returns. So, we don't care about detecting any - # additional errors, so they're squashed so that the rest of the - # post-test-failure cleanup code can continue operation, and - # correctly terminate any log sections, etc. - pass - finally: - self.p.timeout = orig_timeout - - def ensure_spawned(self, expect_reset=False): - """Ensure a connection to a correctly running U-Boot instance. - - This may require spawning a new Sandbox process or resetting target - hardware, as defined by the implementation sub-class. - - This is an internal function and should not be called directly. - - Args: - expect_reset: Boolean indication whether this boot is expected - to be reset while the 1st boot process after main boot before - prompt. False by default. - - Returns: - Nothing. - """ - - if self.p: - # Reset the console timeout value as some tests may change - # its default value during the execution - if not self.config.gdbserver: - self.p.timeout = TIMEOUT_MS - return - try: - self.log.start_section('Starting U-Boot') - self.at_prompt = False - self.p = self.get_spawn() - # Real targets can take a long time to scroll large amounts of - # text if LCD is enabled. This value may need tweaking in the - # future, possibly per-test to be optimal. This works for 'help' - # on board 'seaboard'. - if not self.config.gdbserver: - self.p.timeout = TIMEOUT_MS - self.p.logfile_read = self.logstream - if self.config.use_running_system: - # Send an empty command to set up the 'expect' logic. This has - # the side effect of ensuring that there was no partial command - # line entered - self.run_command(' ') - else: - if expect_reset: - loop_num = 2 - else: - loop_num = 1 - self.wait_for_boot_prompt(loop_num = loop_num) - self.at_prompt = True - self.at_prompt_logevt = self.logstream.logfile.cur_evt - except Exception as ex: - self.log.error(str(ex)) - self.cleanup_spawn() - raise - finally: - self.log.timestamp() - self.log.end_section('Starting U-Boot') - - def cleanup_spawn(self): - """Shut down all interaction with the U-Boot instance. - - This is used when an error is detected prior to re-establishing a - connection with a fresh U-Boot instance. - - This is an internal function and should not be called directly. - - Args: - None. - - Returns: - Nothing. - """ - - try: - if self.p: - self.p.close() - except: - pass - self.p = None - - def restart_uboot(self, expect_reset=False): - """Shut down and restart U-Boot.""" - self.cleanup_spawn() - self.ensure_spawned(expect_reset) - - def get_spawn_output(self): - """Return the start-up output from U-Boot - - Returns: - The output produced by ensure_spawed(), as a string. - """ - if self.p: - return self.p.get_expect_output() - return None - - def validate_version_string_in_text(self, text): - """Assert that a command's output includes the U-Boot signon message. - - This is primarily useful for validating the "version" command without - duplicating the signon text regex in a test function. - - Args: - text: The command output text to check. - - Returns: - Nothing. An exception is raised if the validation fails. - """ - - assert(self.u_boot_version_string in text) - - def disable_check(self, check_type): - """Temporarily disable an error check of U-Boot's output. - - Create a new context manager (for use with the "with" statement) which - temporarily disables a particular console output error check. - - Args: - check_type: The type of error-check to disable. Valid values may - be found in self.disable_check_count above. - - Returns: - A context manager object. - """ - - return ConsoleDisableCheck(self, check_type) - - def enable_check(self, check_type, check_pattern): - """Temporarily enable an error check of U-Boot's output. - - Create a new context manager (for use with the "with" statement) which - temporarily enables a particular console output error check. The - arguments form a new element of bad_pattern_defs defined above. - - Args: - check_type: The type of error-check or bad pattern to enable. - check_pattern: The regexes for text error pattern or bad pattern - to be checked. - - Returns: - A context manager object. - """ - - return ConsoleEnableCheck(self, check_type, check_pattern) - - def temporary_timeout(self, timeout): - """Temporarily set up different timeout for commands. - - Create a new context manager (for use with the "with" statement) which - temporarily change timeout. - - Args: - timeout: Time in milliseconds. - - Returns: - A context manager object. - """ - - return ConsoleSetupTimeout(self, timeout) diff --git a/test/py/u_boot_console_exec_attach.py b/test/py/u_boot_console_exec_attach.py deleted file mode 100644 index 8b253b4451d..00000000000 --- a/test/py/u_boot_console_exec_attach.py +++ /dev/null @@ -1,85 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Copyright (c) 2015 Stephen Warren -# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. - -""" -Logic to interact with U-Boot running on real hardware, typically via a -physical serial port. -""" - -import sys -from u_boot_spawn import Spawn -from u_boot_console_base import ConsoleBase - -class ConsoleExecAttach(ConsoleBase): - """Represents a physical connection to a U-Boot console, typically via a - serial port. This implementation executes a sub-process to attach to the - console, expecting that the stdin/out of the sub-process will be forwarded - to/from the physical hardware. This approach isolates the test infra- - structure from the user-/installation-specific details of how to - communicate with, and the identity of, serial ports etc.""" - - def __init__(self, log, config): - """Initialize a U-Boot console connection. - - Args: - log: A multiplexed_log.Logfile instance. - config: A "configuration" object as defined in conftest.py. - - Returns: - Nothing. - """ - - # The max_fifo_fill value might need tweaking per-board/-SoC? - # 1 would be safe anywhere, but is very slow (a pexpect issue?). - # 16 is a common FIFO size. - # HW flow control would mean this could be infinite. - super(ConsoleExecAttach, self).__init__(log, config, max_fifo_fill=16) - - with self.log.section('flash'): - self.log.action('Flashing U-Boot') - cmd = ['u-boot-test-flash', config.board_type, config.board_identity] - runner = self.log.get_runner(cmd[0], sys.stdout) - runner.run(cmd) - runner.close() - self.log.status_pass('OK') - - def get_spawn(self): - """Connect to a fresh U-Boot instance. - - The target board is reset, so that U-Boot begins running from scratch. - - Args: - None. - - Returns: - A u_boot_spawn.Spawn object that is attached to U-Boot. - """ - - args = [self.config.board_type, self.config.board_identity] - s = Spawn(['u-boot-test-console'] + args) - - if self.config.use_running_system: - self.log.action('Connecting to board without reset') - else: - try: - self.log.action('Resetting board') - cmd = ['u-boot-test-reset'] + args - runner = self.log.get_runner(cmd[0], sys.stdout) - runner.run(cmd) - runner.close() - except: - s.close() - raise - - return s - - def close(self): - super().close() - - self.log.action('Releasing board') - args = [self.config.board_type, self.config.board_identity] - cmd = ['u-boot-test-release'] + args - runner = self.log.get_runner(cmd[0], sys.stdout) - runner.run(cmd) - runner.close() diff --git a/test/py/u_boot_console_sandbox.py b/test/py/u_boot_console_sandbox.py deleted file mode 100644 index 7bc44c78b8b..00000000000 --- a/test/py/u_boot_console_sandbox.py +++ /dev/null @@ -1,119 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Copyright (c) 2015 Stephen Warren -# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. - -""" -Logic to interact with the sandbox port of U-Boot, running as a sub-process. -""" - -import time -from u_boot_spawn import Spawn -from u_boot_console_base import ConsoleBase - -class ConsoleSandbox(ConsoleBase): - """Represents a connection to a sandbox U-Boot console, executed as a sub- - process.""" - - def __init__(self, log, config): - """Initialize a U-Boot console connection. - - Args: - log: A multiplexed_log.Logfile instance. - config: A "configuration" object as defined in conftest.py. - - Returns: - Nothing. - """ - - super(ConsoleSandbox, self).__init__(log, config, max_fifo_fill=1024) - self.sandbox_flags = [] - self.use_dtb = True - - def get_spawn(self): - """Connect to a fresh U-Boot instance. - - A new sandbox process is created, so that U-Boot begins running from - scratch. - - Args: - None. - - Returns: - A u_boot_spawn.Spawn object that is attached to U-Boot. - """ - - bcfg = self.config.buildconfig - config_spl = bcfg.get('config_spl', 'n') == 'y' - config_vpl = bcfg.get('config_vpl', 'n') == 'y' - if config_vpl: - # Run TPL first, which runs VPL - fname = '/tpl/u-boot-tpl' - else: - fname = '/spl/u-boot-spl' if config_spl else '/u-boot' - print(fname) - cmd = [] - if self.config.gdbserver: - cmd += ['gdbserver', self.config.gdbserver] - cmd += [self.config.build_dir + fname, '-v'] - if self.use_dtb: - cmd += ['-d', self.config.dtb] - cmd += self.sandbox_flags - return Spawn(cmd, cwd=self.config.source_dir, decode_signal=True) - - def restart_uboot_with_flags(self, flags, expect_reset=False, use_dtb=True): - """Run U-Boot with the given command-line flags - - Args: - flags: List of flags to pass, each a string - expect_reset: Boolean indication whether this boot is expected - to be reset while the 1st boot process after main boot before - prompt. False by default. - use_dtb: True to use a device tree file, False to run without one - - Returns: - A u_boot_spawn.Spawn object that is attached to U-Boot. - """ - - try: - self.sandbox_flags = flags - self.use_dtb = use_dtb - return self.restart_uboot(expect_reset) - finally: - self.sandbox_flags = [] - self.use_dtb = True - - def kill(self, sig): - """Send a specific Unix signal to the sandbox process. - - Args: - sig: The Unix signal to send to the process. - - Returns: - Nothing. - """ - - self.log.action('kill %d' % sig) - self.p.kill(sig) - - def validate_exited(self): - """Determine whether the sandbox process has exited. - - If required, this function waits a reasonable time for the process to - exit. - - Args: - None. - - Returns: - Boolean indicating whether the process has exited. - """ - - p = self.p - self.p = None - for i in range(100): - ret = not p.isalive() - if ret: - break - time.sleep(0.1) - p.close() - return ret diff --git a/test/py/u_boot_spawn.py b/test/py/u_boot_spawn.py deleted file mode 100644 index c703454389d..00000000000 --- a/test/py/u_boot_spawn.py +++ /dev/null @@ -1,345 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. - -""" -Logic to spawn a sub-process and interact with its stdio. -""" - -import io -import os -import re -import pty -import pytest -import signal -import select -import sys -import termios -import time -import traceback - -# Character to send (twice) to exit the terminal -EXIT_CHAR = 0x1d # FS (Ctrl + ]) - -class Timeout(Exception): - """An exception sub-class that indicates that a timeout occurred.""" - -class BootFail(Exception): - """An exception sub-class that indicates that a boot failure occurred. - - This is used when a bad pattern is seen when waiting for the boot prompt. - It is regarded as fatal, to avoid trying to boot the again and again to no - avail. - """ - -class Unexpected(Exception): - """An exception sub-class that indicates that unexpected test was seen.""" - - -def handle_exception(ubconfig, console, log, err, name, fatal, output=''): - """Handle an exception from the console - - Exceptions can occur when there is unexpected output or due to the board - crashing or hanging. Some exceptions are likely fatal, where retrying will - just chew up time to no available. In those cases it is best to cause - further tests be skipped. - - Args: - ubconfig (ArbitraryAttributeContainer): ubconfig object - log (Logfile): Place to log errors - console (ConsoleBase): Console to clean up, if fatal - err (Exception): Exception which was thrown - name (str): Name of problem, to log - fatal (bool): True to abort all tests - output (str): Extra output to report on boot failure. This can show the - target's console output as it tried to boot - """ - msg = f'{name}: ' - if fatal: - msg += 'Marking connection bad - no other tests will run' - else: - msg += 'Assuming that lab is healthy' - print(msg) - log.error(msg) - log.error(f'Error: {err}') - - if output: - msg += f'; output {output}' - - if fatal: - ubconfig.connection_ok = False - console.cleanup_spawn() - pytest.exit(msg) - - -class Spawn: - """Represents the stdio of a freshly created sub-process. Commands may be - sent to the process, and responses waited for. - - Members: - output: accumulated output from expect() - """ - - def __init__(self, args, cwd=None, decode_signal=False): - """Spawn (fork/exec) the sub-process. - - Args: - args: array of processs arguments. argv[0] is the command to - execute. - cwd: the directory to run the process in, or None for no change. - decode_signal (bool): True to indicate the exception number when - something goes wrong - - Returns: - Nothing. - """ - self.decode_signal = decode_signal - self.waited = False - self.exit_code = 0 - self.exit_info = '' - self.buf = '' - self.output = '' - self.logfile_read = None - self.before = '' - self.after = '' - self.timeout = None - # http://stackoverflow.com/questions/7857352/python-regex-to-match-vt100-escape-sequences - self.re_vt100 = re.compile(r'(\x1b\[|\x9b)[^@-_]*[@-_]|\x1b[@-_]', re.I) - - (self.pid, self.fd) = pty.fork() - if self.pid == 0: - try: - # For some reason, SIGHUP is set to SIG_IGN at this point when - # run under "go" (www.go.cd). Perhaps this happens under any - # background (non-interactive) system? - signal.signal(signal.SIGHUP, signal.SIG_DFL) - if cwd: - os.chdir(cwd) - os.execvp(args[0], args) - except: - print('CHILD EXECEPTION:') - traceback.print_exc() - finally: - os._exit(255) - - old = None - try: - isatty = False - try: - isatty = os.isatty(sys.stdout.fileno()) - - # with --capture=tee-sys we cannot call fileno() - except io.UnsupportedOperation as exc: - pass - if isatty: - new = termios.tcgetattr(self.fd) - old = new - new[3] = new[3] & ~(termios.ICANON | termios.ISIG) - new[3] = new[3] & ~termios.ECHO - new[6][termios.VMIN] = 0 - new[6][termios.VTIME] = 0 - termios.tcsetattr(self.fd, termios.TCSANOW, new) - - self.poll = select.poll() - self.poll.register(self.fd, select.POLLIN | select.POLLPRI | select.POLLERR | - select.POLLHUP | select.POLLNVAL) - except: - if old: - termios.tcsetattr(self.fd, termios.TCSANOW, old) - self.close() - raise - - def kill(self, sig): - """Send unix signal "sig" to the child process. - - Args: - sig: The signal number to send. - - Returns: - Nothing. - """ - - os.kill(self.pid, sig) - - def checkalive(self): - """Determine whether the child process is still running. - - Returns: - tuple: - True if process is alive, else False - 0 if process is alive, else exit code of process - string describing what happened ('' or 'status/signal n') - """ - - if self.waited: - return False, self.exit_code, self.exit_info - - w = os.waitpid(self.pid, os.WNOHANG) - if w[0] == 0: - return True, 0, 'running' - status = w[1] - - if os.WIFEXITED(status): - self.exit_code = os.WEXITSTATUS(status) - self.exit_info = 'status %d' % self.exit_code - elif os.WIFSIGNALED(status): - signum = os.WTERMSIG(status) - self.exit_code = -signum - self.exit_info = 'signal %d (%s)' % (signum, signal.Signals(signum).name) - self.waited = True - return False, self.exit_code, self.exit_info - - def isalive(self): - """Determine whether the child process is still running. - - Args: - None. - - Returns: - Boolean indicating whether process is alive. - """ - return self.checkalive()[0] - - def send(self, data): - """Send data to the sub-process's stdin. - - Args: - data: The data to send to the process. - - Returns: - Nothing. - """ - - os.write(self.fd, data.encode(errors='replace')) - - def receive(self, num_bytes): - """Receive data from the sub-process's stdin. - - Args: - num_bytes (int): Maximum number of bytes to read - - Returns: - str: The data received - - Raises: - ValueError if U-Boot died - """ - try: - c = os.read(self.fd, num_bytes).decode(errors='replace') - except OSError as err: - # With sandbox, try to detect when U-Boot exits when it - # shouldn't and explain why. This is much more friendly than - # just dying with an I/O error - if self.decode_signal and err.errno == 5: # I/O error - alive, _, info = self.checkalive() - if alive: - raise err - raise ValueError('U-Boot exited with %s' % info) - raise - return c - - def expect(self, patterns): - """Wait for the sub-process to emit specific data. - - This function waits for the process to emit one pattern from the - supplied list of patterns, or for a timeout to occur. - - Args: - patterns: A list of strings or regex objects that we expect to - see in the sub-process' stdout. - - Returns: - The index within the patterns array of the pattern the process - emitted. - - Notable exceptions: - Timeout, if the process did not emit any of the patterns within - the expected time. - """ - - for pi in range(len(patterns)): - if type(patterns[pi]) == type(''): - patterns[pi] = re.compile(patterns[pi]) - - tstart_s = time.time() - try: - while True: - earliest_m = None - earliest_pi = None - for pi in range(len(patterns)): - pattern = patterns[pi] - m = pattern.search(self.buf) - if not m: - continue - if earliest_m and m.start() >= earliest_m.start(): - continue - earliest_m = m - earliest_pi = pi - if earliest_m: - pos = earliest_m.start() - posafter = earliest_m.end() - self.before = self.buf[:pos] - self.after = self.buf[pos:posafter] - self.output += self.buf[:posafter] - self.buf = self.buf[posafter:] - return earliest_pi - tnow_s = time.time() - if self.timeout: - tdelta_ms = (tnow_s - tstart_s) * 1000 - poll_maxwait = self.timeout - tdelta_ms - if tdelta_ms > self.timeout: - raise Timeout() - else: - poll_maxwait = None - events = self.poll.poll(poll_maxwait) - if not events: - raise Timeout() - c = self.receive(1024) - if self.logfile_read: - self.logfile_read.write(c) - self.buf += c - # count=0 is supposed to be the default, which indicates - # unlimited substitutions, but in practice the version of - # Python in Ubuntu 14.04 appears to default to count=2! - self.buf = self.re_vt100.sub('', self.buf, count=1000000) - finally: - if self.logfile_read: - self.logfile_read.flush() - - def close(self): - """Close the stdio connection to the sub-process. - - This also waits a reasonable time for the sub-process to stop running. - - Args: - None. - - Returns: - str: Type of closure completed - """ - # For Labgrid-sjg, ask it is exit gracefully, so it can transition the - # board to the final state (like 'off') before exiting. - if os.environ.get('USE_LABGRID_SJG'): - self.send(chr(EXIT_CHAR) * 2) - - # Wait about 10 seconds for Labgrid to close and power off the board - for _ in range(100): - if not self.isalive(): - return 'normal' - time.sleep(0.1) - - # That didn't work, so try closing the PTY - os.close(self.fd) - for _ in range(100): - if not self.isalive(): - return 'break' - time.sleep(0.1) - - return 'timeout' - - def get_expect_output(self): - """Return the output read by expect() - - Returns: - The output processed by expect(), as a string. - """ - return self.output diff --git a/test/py/u_boot_utils.py b/test/py/u_boot_utils.py deleted file mode 100644 index ca80e4b0b0a..00000000000 --- a/test/py/u_boot_utils.py +++ /dev/null @@ -1,382 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. - -""" -Utility code shared across multiple tests. -""" - -import hashlib -import inspect -import os -import os.path -import pathlib -import signal -import sys -import time -import re -import pytest - -def md5sum_data(data): - """Calculate the MD5 hash of some data. - - Args: - data: The data to hash. - - Returns: - The hash of the data, as a binary string. - """ - - h = hashlib.md5() - h.update(data) - return h.digest() - -def md5sum_file(fn, max_length=None): - """Calculate the MD5 hash of the contents of a file. - - Args: - fn: The filename of the file to hash. - max_length: The number of bytes to hash. If the file has more - bytes than this, they will be ignored. If None or omitted, the - entire file will be hashed. - - Returns: - The hash of the file content, as a binary string. - """ - - with open(fn, 'rb') as fh: - if max_length: - params = [max_length] - else: - params = [] - data = fh.read(*params) - return md5sum_data(data) - -class PersistentRandomFile: - """Generate and store information about a persistent file containing - random data.""" - - def __init__(self, ubman, fn, size): - """Create or process the persistent file. - - If the file does not exist, it is generated. - - If the file does exist, its content is hashed for later comparison. - - These files are always located in the "persistent data directory" of - the current test run. - - Args: - ubman: A console connection to U-Boot. - fn: The filename (without path) to create. - size: The desired size of the file in bytes. - - Returns: - Nothing. - """ - - self.fn = fn - - self.abs_fn = ubman.config.persistent_data_dir + '/' + fn - - if os.path.exists(self.abs_fn): - ubman.log.action('Persistent data file ' + self.abs_fn + - ' already exists') - self.content_hash = md5sum_file(self.abs_fn) - else: - ubman.log.action('Generating ' + self.abs_fn + - ' (random, persistent, %d bytes)' % size) - data = os.urandom(size) - with open(self.abs_fn, 'wb') as fh: - fh.write(data) - self.content_hash = md5sum_data(data) - -def attempt_to_open_file(fn): - """Attempt to open a file, without throwing exceptions. - - Any errors (exceptions) that occur during the attempt to open the file - are ignored. This is useful in order to test whether a file (in - particular, a device node) exists and can be successfully opened, in order - to poll for e.g. USB enumeration completion. - - Args: - fn: The filename to attempt to open. - - Returns: - An open file handle to the file, or None if the file could not be - opened. - """ - - try: - return open(fn, 'rb') - except: - return None - -def wait_until_open_succeeds(fn): - """Poll until a file can be opened, or a timeout occurs. - - Continually attempt to open a file, and return when this succeeds, or - raise an exception after a timeout. - - Args: - fn: The filename to attempt to open. - - Returns: - An open file handle to the file. - """ - - for i in range(100): - fh = attempt_to_open_file(fn) - if fh: - return fh - time.sleep(0.1) - raise Exception('File could not be opened') - -def wait_until_file_open_fails(fn, ignore_errors): - """Poll until a file cannot be opened, or a timeout occurs. - - Continually attempt to open a file, and return when this fails, or - raise an exception after a timeout. - - Args: - fn: The filename to attempt to open. - ignore_errors: Indicate whether to ignore timeout errors. If True, the - function will simply return if a timeout occurs, otherwise an - exception will be raised. - - Returns: - Nothing. - """ - - for _ in range(100): - fh = attempt_to_open_file(fn) - if not fh: - return - fh.close() - time.sleep(0.1) - if ignore_errors: - return - raise Exception('File can still be opened') - -def run_and_log(ubman, cmd, ignore_errors=False, stdin=None, env=None): - """Run a command and log its output. - - Args: - ubman: A console connection to U-Boot. - cmd: The command to run, as an array of argv[], or a string. - If a string, note that it is split up so that quoted spaces - will not be preserved. E.g. "fred and" becomes ['"fred', 'and"'] - ignore_errors: Indicate whether to ignore errors. If True, the function - will simply return if the command cannot be executed or exits with - an error code, otherwise an exception will be raised if such - problems occur. - stdin: Input string to pass to the command as stdin (or None) - env: Environment to use, or None to use the current one - - Returns: - The output as a string. - """ - if isinstance(cmd, str): - cmd = cmd.split() - runner = ubman.log.get_runner(cmd[0], sys.stdout) - output = runner.run(cmd, ignore_errors=ignore_errors, stdin=stdin, env=env) - runner.close() - return output - -def run_and_log_expect_exception(ubman, cmd, retcode, msg): - """Run a command that is expected to fail. - - This runs a command and checks that it fails with the expected return code - and exception method. If not, an exception is raised. - - Args: - ubman: A console connection to U-Boot. - cmd: The command to run, as an array of argv[]. - retcode: Expected non-zero return code from the command. - msg: String that should be contained within the command's output. - """ - try: - runner = ubman.log.get_runner(cmd[0], sys.stdout) - runner.run(cmd) - except Exception: - assert retcode == runner.exit_status - assert msg in runner.output - else: - raise Exception("Expected an exception with retcode %d message '%s'," - "but it was not raised" % (retcode, msg)) - finally: - runner.close() - -ram_base = None -def find_ram_base(ubman): - """Find the running U-Boot's RAM location. - - Probe the running U-Boot to determine the address of the first bank - of RAM. This is useful for tests that test reading/writing RAM, or - load/save files that aren't associated with some standard address - typically represented in an environment variable such as - ${kernel_addr_r}. The value is cached so that it only needs to be - actively read once. - - Args: - ubman: A console connection to U-Boot. - - Returns: - The address of U-Boot's first RAM bank, as an integer. - """ - - global ram_base - if ubman.config.buildconfig.get('config_cmd_bdi', 'n') != 'y': - pytest.skip('bdinfo command not supported') - if ram_base == -1: - pytest.skip('Previously failed to find RAM bank start') - if ram_base is not None: - return ram_base - - with ubman.log.section('find_ram_base'): - response = ubman.run_command('bdinfo') - for l in response.split('\n'): - if '-> start' in l or 'memstart =' in l: - ram_base = int(l.split('=')[1].strip(), 16) - break - if ram_base is None: - ram_base = -1 - raise Exception('Failed to find RAM bank start in `bdinfo`') - - # We don't want ram_base to be zero as some functions test if the given - # address is NULL (0). Besides, on some RISC-V targets the low memory - # is protected that prevents S-mode U-Boot from access. - # Let's add 2MiB then (size of an ARM LPAE/v8 section). - - ram_base += 1024 * 1024 * 2 - - return ram_base - -class PersistentFileHelperCtxMgr(object): - """A context manager for Python's "with" statement, which ensures that any - generated file is deleted (and hence regenerated) if its mtime is older - than the mtime of the Python module which generated it, and gets an mtime - newer than the mtime of the Python module which generated after it is - generated. Objects of this type should be created by factory function - persistent_file_helper rather than directly.""" - - def __init__(self, log, filename): - """Initialize a new object. - - Args: - log: The Logfile object to log to. - filename: The filename of the generated file. - - Returns: - Nothing. - """ - - self.log = log - self.filename = filename - - def __enter__(self): - frame = inspect.stack()[1] - module = inspect.getmodule(frame[0]) - self.module_filename = module.__file__ - self.module_timestamp = os.path.getmtime(self.module_filename) - - if os.path.exists(self.filename): - filename_timestamp = os.path.getmtime(self.filename) - if filename_timestamp < self.module_timestamp: - self.log.action('Removing stale generated file ' + - self.filename) - pathlib.Path(self.filename).unlink() - - def __exit__(self, extype, value, traceback): - if extype: - try: - pathlib.Path(self.filename).unlink() - except Exception: - pass - return - logged = False - for _ in range(20): - filename_timestamp = os.path.getmtime(self.filename) - if filename_timestamp > self.module_timestamp: - break - if not logged: - self.log.action( - 'Waiting for generated file timestamp to increase') - logged = True - os.utime(self.filename) - time.sleep(0.1) - -def persistent_file_helper(u_boot_log, filename): - """Manage the timestamps and regeneration of a persistent generated - file. This function creates a context manager for Python's "with" - statement - - Usage: - with persistent_file_helper(ubman.log, filename): - code to generate the file, if it's missing. - - Args: - u_boot_log: ubman.log. - filename: The filename of the generated file. - - Returns: - A context manager object. - """ - - return PersistentFileHelperCtxMgr(u_boot_log, filename) - -def crc32(ubman, address, count): - """Helper function used to compute the CRC32 value of a section of RAM. - - Args: - ubman: A U-Boot console connection. - address: Address where data starts. - count: Amount of data to use for calculation. - - Returns: - CRC32 value - """ - - bcfg = ubman.config.buildconfig - has_cmd_crc32 = bcfg.get('config_cmd_crc32', 'n') == 'y' - assert has_cmd_crc32, 'Cannot compute crc32 without CONFIG_CMD_CRC32.' - output = ubman.run_command('crc32 %08x %x' % (address, count)) - - m = re.search('==> ([0-9a-fA-F]{8})$', output) - assert m, 'CRC32 operation failed.' - - return m.group(1) - -def waitpid(pid, timeout=60, kill=False): - """Wait a process to terminate by its PID - - This is an alternative to a os.waitpid(pid, 0) call that works on - processes that aren't children of the python process. - - Args: - pid: PID of a running process. - timeout: Time in seconds to wait. - kill: Whether to forcibly kill the process after timeout. - - Returns: - True, if the process ended on its own. - False, if the process was killed by this function. - - Raises: - TimeoutError, if the process is still running after timeout. - """ - try: - for _ in range(timeout): - os.kill(pid, 0) - time.sleep(1) - - if kill: - os.kill(pid, signal.SIGKILL) - return False - - except ProcessLookupError: - return True - - raise TimeoutError( - "Process with PID {} did not terminate after {} seconds." - .format(pid, timeout) - ) diff --git a/test/py/utils.py b/test/py/utils.py new file mode 100644 index 00000000000..ca80e4b0b0a --- /dev/null +++ b/test/py/utils.py @@ -0,0 +1,382 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + +""" +Utility code shared across multiple tests. +""" + +import hashlib +import inspect +import os +import os.path +import pathlib +import signal +import sys +import time +import re +import pytest + +def md5sum_data(data): + """Calculate the MD5 hash of some data. + + Args: + data: The data to hash. + + Returns: + The hash of the data, as a binary string. + """ + + h = hashlib.md5() + h.update(data) + return h.digest() + +def md5sum_file(fn, max_length=None): + """Calculate the MD5 hash of the contents of a file. + + Args: + fn: The filename of the file to hash. + max_length: The number of bytes to hash. If the file has more + bytes than this, they will be ignored. If None or omitted, the + entire file will be hashed. + + Returns: + The hash of the file content, as a binary string. + """ + + with open(fn, 'rb') as fh: + if max_length: + params = [max_length] + else: + params = [] + data = fh.read(*params) + return md5sum_data(data) + +class PersistentRandomFile: + """Generate and store information about a persistent file containing + random data.""" + + def __init__(self, ubman, fn, size): + """Create or process the persistent file. + + If the file does not exist, it is generated. + + If the file does exist, its content is hashed for later comparison. + + These files are always located in the "persistent data directory" of + the current test run. + + Args: + ubman: A console connection to U-Boot. + fn: The filename (without path) to create. + size: The desired size of the file in bytes. + + Returns: + Nothing. + """ + + self.fn = fn + + self.abs_fn = ubman.config.persistent_data_dir + '/' + fn + + if os.path.exists(self.abs_fn): + ubman.log.action('Persistent data file ' + self.abs_fn + + ' already exists') + self.content_hash = md5sum_file(self.abs_fn) + else: + ubman.log.action('Generating ' + self.abs_fn + + ' (random, persistent, %d bytes)' % size) + data = os.urandom(size) + with open(self.abs_fn, 'wb') as fh: + fh.write(data) + self.content_hash = md5sum_data(data) + +def attempt_to_open_file(fn): + """Attempt to open a file, without throwing exceptions. + + Any errors (exceptions) that occur during the attempt to open the file + are ignored. This is useful in order to test whether a file (in + particular, a device node) exists and can be successfully opened, in order + to poll for e.g. USB enumeration completion. + + Args: + fn: The filename to attempt to open. + + Returns: + An open file handle to the file, or None if the file could not be + opened. + """ + + try: + return open(fn, 'rb') + except: + return None + +def wait_until_open_succeeds(fn): + """Poll until a file can be opened, or a timeout occurs. + + Continually attempt to open a file, and return when this succeeds, or + raise an exception after a timeout. + + Args: + fn: The filename to attempt to open. + + Returns: + An open file handle to the file. + """ + + for i in range(100): + fh = attempt_to_open_file(fn) + if fh: + return fh + time.sleep(0.1) + raise Exception('File could not be opened') + +def wait_until_file_open_fails(fn, ignore_errors): + """Poll until a file cannot be opened, or a timeout occurs. + + Continually attempt to open a file, and return when this fails, or + raise an exception after a timeout. + + Args: + fn: The filename to attempt to open. + ignore_errors: Indicate whether to ignore timeout errors. If True, the + function will simply return if a timeout occurs, otherwise an + exception will be raised. + + Returns: + Nothing. + """ + + for _ in range(100): + fh = attempt_to_open_file(fn) + if not fh: + return + fh.close() + time.sleep(0.1) + if ignore_errors: + return + raise Exception('File can still be opened') + +def run_and_log(ubman, cmd, ignore_errors=False, stdin=None, env=None): + """Run a command and log its output. + + Args: + ubman: A console connection to U-Boot. + cmd: The command to run, as an array of argv[], or a string. + If a string, note that it is split up so that quoted spaces + will not be preserved. E.g. "fred and" becomes ['"fred', 'and"'] + ignore_errors: Indicate whether to ignore errors. If True, the function + will simply return if the command cannot be executed or exits with + an error code, otherwise an exception will be raised if such + problems occur. + stdin: Input string to pass to the command as stdin (or None) + env: Environment to use, or None to use the current one + + Returns: + The output as a string. + """ + if isinstance(cmd, str): + cmd = cmd.split() + runner = ubman.log.get_runner(cmd[0], sys.stdout) + output = runner.run(cmd, ignore_errors=ignore_errors, stdin=stdin, env=env) + runner.close() + return output + +def run_and_log_expect_exception(ubman, cmd, retcode, msg): + """Run a command that is expected to fail. + + This runs a command and checks that it fails with the expected return code + and exception method. If not, an exception is raised. + + Args: + ubman: A console connection to U-Boot. + cmd: The command to run, as an array of argv[]. + retcode: Expected non-zero return code from the command. + msg: String that should be contained within the command's output. + """ + try: + runner = ubman.log.get_runner(cmd[0], sys.stdout) + runner.run(cmd) + except Exception: + assert retcode == runner.exit_status + assert msg in runner.output + else: + raise Exception("Expected an exception with retcode %d message '%s'," + "but it was not raised" % (retcode, msg)) + finally: + runner.close() + +ram_base = None +def find_ram_base(ubman): + """Find the running U-Boot's RAM location. + + Probe the running U-Boot to determine the address of the first bank + of RAM. This is useful for tests that test reading/writing RAM, or + load/save files that aren't associated with some standard address + typically represented in an environment variable such as + ${kernel_addr_r}. The value is cached so that it only needs to be + actively read once. + + Args: + ubman: A console connection to U-Boot. + + Returns: + The address of U-Boot's first RAM bank, as an integer. + """ + + global ram_base + if ubman.config.buildconfig.get('config_cmd_bdi', 'n') != 'y': + pytest.skip('bdinfo command not supported') + if ram_base == -1: + pytest.skip('Previously failed to find RAM bank start') + if ram_base is not None: + return ram_base + + with ubman.log.section('find_ram_base'): + response = ubman.run_command('bdinfo') + for l in response.split('\n'): + if '-> start' in l or 'memstart =' in l: + ram_base = int(l.split('=')[1].strip(), 16) + break + if ram_base is None: + ram_base = -1 + raise Exception('Failed to find RAM bank start in `bdinfo`') + + # We don't want ram_base to be zero as some functions test if the given + # address is NULL (0). Besides, on some RISC-V targets the low memory + # is protected that prevents S-mode U-Boot from access. + # Let's add 2MiB then (size of an ARM LPAE/v8 section). + + ram_base += 1024 * 1024 * 2 + + return ram_base + +class PersistentFileHelperCtxMgr(object): + """A context manager for Python's "with" statement, which ensures that any + generated file is deleted (and hence regenerated) if its mtime is older + than the mtime of the Python module which generated it, and gets an mtime + newer than the mtime of the Python module which generated after it is + generated. Objects of this type should be created by factory function + persistent_file_helper rather than directly.""" + + def __init__(self, log, filename): + """Initialize a new object. + + Args: + log: The Logfile object to log to. + filename: The filename of the generated file. + + Returns: + Nothing. + """ + + self.log = log + self.filename = filename + + def __enter__(self): + frame = inspect.stack()[1] + module = inspect.getmodule(frame[0]) + self.module_filename = module.__file__ + self.module_timestamp = os.path.getmtime(self.module_filename) + + if os.path.exists(self.filename): + filename_timestamp = os.path.getmtime(self.filename) + if filename_timestamp < self.module_timestamp: + self.log.action('Removing stale generated file ' + + self.filename) + pathlib.Path(self.filename).unlink() + + def __exit__(self, extype, value, traceback): + if extype: + try: + pathlib.Path(self.filename).unlink() + except Exception: + pass + return + logged = False + for _ in range(20): + filename_timestamp = os.path.getmtime(self.filename) + if filename_timestamp > self.module_timestamp: + break + if not logged: + self.log.action( + 'Waiting for generated file timestamp to increase') + logged = True + os.utime(self.filename) + time.sleep(0.1) + +def persistent_file_helper(u_boot_log, filename): + """Manage the timestamps and regeneration of a persistent generated + file. This function creates a context manager for Python's "with" + statement + + Usage: + with persistent_file_helper(ubman.log, filename): + code to generate the file, if it's missing. + + Args: + u_boot_log: ubman.log. + filename: The filename of the generated file. + + Returns: + A context manager object. + """ + + return PersistentFileHelperCtxMgr(u_boot_log, filename) + +def crc32(ubman, address, count): + """Helper function used to compute the CRC32 value of a section of RAM. + + Args: + ubman: A U-Boot console connection. + address: Address where data starts. + count: Amount of data to use for calculation. + + Returns: + CRC32 value + """ + + bcfg = ubman.config.buildconfig + has_cmd_crc32 = bcfg.get('config_cmd_crc32', 'n') == 'y' + assert has_cmd_crc32, 'Cannot compute crc32 without CONFIG_CMD_CRC32.' + output = ubman.run_command('crc32 %08x %x' % (address, count)) + + m = re.search('==> ([0-9a-fA-F]{8})$', output) + assert m, 'CRC32 operation failed.' + + return m.group(1) + +def waitpid(pid, timeout=60, kill=False): + """Wait a process to terminate by its PID + + This is an alternative to a os.waitpid(pid, 0) call that works on + processes that aren't children of the python process. + + Args: + pid: PID of a running process. + timeout: Time in seconds to wait. + kill: Whether to forcibly kill the process after timeout. + + Returns: + True, if the process ended on its own. + False, if the process was killed by this function. + + Raises: + TimeoutError, if the process is still running after timeout. + """ + try: + for _ in range(timeout): + os.kill(pid, 0) + time.sleep(1) + + if kill: + os.kill(pid, signal.SIGKILL) + return False + + except ProcessLookupError: + return True + + raise TimeoutError( + "Process with PID {} did not terminate after {} seconds." + .format(pid, timeout) + ) -- cgit v1.3.1 From dd693ecb60384049dd8c3f6a36331c1a70b6558f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 9 Feb 2025 09:07:16 -0700 Subject: test/py: Drop importing utils as util Now that we have a shorter name, we don't need this sort of thing. Drop it. Signed-off-by: Simon Glass Reviewed-by: Mattijs Korpershoek # test_android --- test/py/tests/fit_util.py | 6 +-- test/py/tests/test_android/test_avb.py | 1 - test/py/tests/test_efi_fit.py | 24 ++++++------ test/py/tests/test_event_dump.py | 4 +- test/py/tests/test_fit.py | 4 +- test/py/tests/test_fit_auto_signed.py | 18 ++++----- test/py/tests/test_fit_ecdsa.py | 16 ++++---- test/py/tests/test_fit_hashes.py | 14 ++++--- test/py/tests/test_fs/conftest.py | 1 - test/py/tests/test_kconfig.py | 6 +-- test/py/tests/test_of_migrate.py | 14 +++---- test/py/tests/test_ofplatdata.py | 4 +- test/py/tests/test_optee_rpmb.py | 2 +- test/py/tests/test_sandbox_opts.py | 6 +-- test/py/tests/test_scp03.py | 2 +- test/py/tests/test_source.py | 4 +- test/py/tests/test_trace.py | 18 ++++----- test/py/tests/test_vboot.py | 70 +++++++++++++++++----------------- 18 files changed, 110 insertions(+), 104 deletions(-) (limited to 'test/py/tests/test_android') diff --git a/test/py/tests/fit_util.py b/test/py/tests/fit_util.py index 22b971131b8..f322b50a319 100644 --- a/test/py/tests/fit_util.py +++ b/test/py/tests/fit_util.py @@ -5,7 +5,7 @@ import os -import utils as util +import utils def make_fname(ubman, basename): """Make a temporary filename @@ -54,7 +54,7 @@ def make_fit(ubman, mkimage, base_its, params, basename='test.fit', base_fdt=Non """ fit = make_fname(ubman, basename) its = make_its(ubman, base_its, params) - util.run_and_log(ubman, [mkimage, '-f', its, fit]) + utils.run_and_log(ubman, [mkimage, '-f', its, fit]) if base_fdt: with open(make_fname(ubman, 'u-boot.dts'), 'w') as fd: fd.write(base_fdt) @@ -89,5 +89,5 @@ def make_dtb(ubman, base_fdt, basename): dtb = make_fname(ubman, f'{basename}.dtb') with open(src, 'w', encoding='utf-8') as outf: outf.write(base_fdt) - util.run_and_log(ubman, ['dtc', src, '-O', 'dtb', '-o', dtb]) + utils.run_and_log(ubman, ['dtc', src, '-O', 'dtb', '-o', dtb]) return dtb diff --git a/test/py/tests/test_android/test_avb.py b/test/py/tests/test_android/test_avb.py index 1d600b95c6f..137d83e1dea 100644 --- a/test/py/tests/test_android/test_avb.py +++ b/test/py/tests/test_android/test_avb.py @@ -15,7 +15,6 @@ For configuration verification: """ import pytest -import utils as util # defauld mmc id mmc_dev = 1 diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py index c836834845e..e7d523a77d5 100644 --- a/test/py/tests/test_efi_fit.py +++ b/test/py/tests/test_efi_fit.py @@ -55,7 +55,7 @@ env__efi_fit_tftp_file = { import os.path import pytest -import utils as util +import utils # Define the parametrized ITS data to be used for FIT images generation. ITS_DATA = ''' @@ -224,11 +224,11 @@ def test_efi_fit_launch(ubman): """ bin_path = make_fpath(fname) - util.run_and_log(cons, - ['cp', make_fpath('lib/efi_loader/helloworld.efi'), - bin_path]) + utils.run_and_log(cons, + ['cp', make_fpath('lib/efi_loader/helloworld.efi'), + bin_path]) if comp: - util.run_and_log(cons, ['gzip', '-f', bin_path]) + utils.run_and_log(cons, ['gzip', '-f', bin_path]) bin_path += '.gz' return bin_path @@ -257,9 +257,10 @@ def test_efi_fit_launch(ubman): # Build the test FDT. dtb = make_fpath('test-efi-fit-%s.dtb' % fdt_type) - util.run_and_log(cons, ['dtc', '-I', 'dts', '-O', 'dtb', '-o', dtb, dts]) + utils.run_and_log(cons, + ['dtc', '-I', 'dts', '-O', 'dtb', '-o', dtb, dts]) if comp: - util.run_and_log(cons, ['gzip', '-f', dtb]) + utils.run_and_log(cons, ['gzip', '-f', dtb]) dtb += '.gz' return dtb @@ -290,7 +291,7 @@ def test_efi_fit_launch(ubman): # Build the test ITS. fit_path = make_fpath('test-efi-fit-helloworld.fit') - util.run_and_log( + utils.run_and_log( cons, [make_fpath('tools/mkimage'), '-f', its_path, fit_path]) return fit_path @@ -307,7 +308,7 @@ def test_efi_fit_launch(ubman): addr = fit.get('addr', None) if not addr: - addr = util.find_ram_base(cons) + addr = utils.find_ram_base(cons) output = cons.run_command( 'host load hostfs - %x %s/%s' % (addr, fit['dn'], fit['fn'])) @@ -334,7 +335,7 @@ def test_efi_fit_launch(ubman): addr = fit.get('addr', None) if not addr: - addr = util.find_ram_base(cons) + addr = utils.find_ram_base(cons) file_name = fit['fn'] output = cons.run_command('tftpboot %x %s' % (addr, file_name)) @@ -412,7 +413,8 @@ def test_efi_fit_launch(ubman): # Copy image to TFTP root directory. if fit['dn'] != cons.config.build_dir: - util.run_and_log(cons, ['mv', '-f', fit_path, '%s/' % fit['dn']]) + utils.run_and_log(cons, + ['mv', '-f', fit_path, '%s/' % fit['dn']]) # Load FIT image. addr = load_fit_from_host(fit) if is_sandbox else load_fit_from_tftp(fit) diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py index 5a9d39da74c..8297663fbff 100644 --- a/test/py/tests/test_event_dump.py +++ b/test/py/tests/test_event_dump.py @@ -4,7 +4,7 @@ import pytest import re -import utils as util +import utils # This is only a partial test - coverting 64-bit sandbox. It does not test # big-endian images, nor 32-bit images @@ -13,7 +13,7 @@ def test_event_dump(ubman): """Test that the "help" command can be executed.""" cons = ubman sandbox = cons.config.build_dir + '/u-boot' - out = util.run_and_log(cons, ['scripts/event_dump.py', sandbox]) + out = utils.run_and_log(cons, ['scripts/event_dump.py', sandbox]) expect = '''.*Event type Id Source location -------------------- ------------------------------ ------------------------------ EVT_FT_FIXUP bootmeth_vbe_ft_fixup .*boot/vbe_request.c:.* diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 0f2d0940562..bfc20c4b1ed 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -6,7 +6,7 @@ import os import pytest import struct -import utils as util +import utils import fit_util # Define a base ITS which we can adjust using % and a dictionary @@ -165,7 +165,7 @@ def test_fit(ubman): return fname def make_compressed(filename): - util.run_and_log(cons, ['gzip', '-f', '-k', filename]) + utils.run_and_log(cons, ['gzip', '-f', '-k', filename]) return filename + '.gz' def find_matching(text, match): diff --git a/test/py/tests/test_fit_auto_signed.py b/test/py/tests/test_fit_auto_signed.py index bee93e4f084..b5f872f3d0f 100644 --- a/test/py/tests/test_fit_auto_signed.py +++ b/test/py/tests/test_fit_auto_signed.py @@ -17,7 +17,7 @@ The test does not run the sandbox. It only checks the host tool mkimage. import os import pytest -import utils as util +import utils import binascii from Cryptodome.Hash import SHA1 from Cryptodome.Hash import SHA256 @@ -33,15 +33,15 @@ class SignedFitHelper(object): self.confgs_nodes = set() def __fdt_list(self, path): - return util.run_and_log(self.cons, + return utils.run_and_log(self.cons, f'fdtget -l {self.fit} {path}') def __fdt_get_string(self, node, prop): - return util.run_and_log(self.cons, + return utils.run_and_log(self.cons, f'fdtget -ts {self.fit} {node} {prop}') def __fdt_get_binary(self, node, prop): - numbers = util.run_and_log(self.cons, + numbers = utils.run_and_log(self.cons, f'fdtget -tbi {self.fit} {node} {prop}') bignum = bytearray() @@ -166,7 +166,7 @@ def test_fit_auto_signed(ubman): s_args = " -k" + tempdir + " -g" + key_name + " -o" + sign_algo # 1 - Create auto FIT with images crc32 checksum, and verify it - util.run_and_log(cons, mkimage + ' -fauto' + b_args + " " + fit_file) + utils.run_and_log(cons, mkimage + ' -fauto' + b_args + " " + fit_file) fit = SignedFitHelper(cons, fit_file) if fit.build_nodes_sets() == 0: @@ -175,8 +175,8 @@ def test_fit_auto_signed(ubman): fit.check_fit_crc32_images() # 2 - Create auto FIT with signed images, and verify it - util.run_and_log(cons, mkimage + ' -fauto' + b_args + s_args + " " + - fit_file) + utils.run_and_log(cons, mkimage + ' -fauto' + b_args + s_args + " " + + fit_file) fit = SignedFitHelper(cons, fit_file) if fit.build_nodes_sets() == 0: @@ -185,8 +185,8 @@ def test_fit_auto_signed(ubman): fit.check_fit_signed_images(key_name, sign_algo, verifier) # 3 - Create auto FIT with signed configs and hashed images, and verify it - util.run_and_log(cons, mkimage + ' -fauto-conf' + b_args + s_args + " " + - fit_file) + utils.run_and_log(cons, mkimage + ' -fauto-conf' + b_args + s_args + " " + + fit_file) fit = SignedFitHelper(cons, fit_file) if fit.build_nodes_sets() == 0: diff --git a/test/py/tests/test_fit_ecdsa.py b/test/py/tests/test_fit_ecdsa.py index 7b25c7779c6..63f2f6a44e6 100644 --- a/test/py/tests/test_fit_ecdsa.py +++ b/test/py/tests/test_fit_ecdsa.py @@ -12,7 +12,7 @@ This test doesn't run the sandbox. It only checks the host tool 'mkimage' import os import pytest -import utils as util +import utils from Cryptodome.Hash import SHA256 from Cryptodome.PublicKey import ECC from Cryptodome.Signature import DSS @@ -25,14 +25,16 @@ class SignableFitImage(object): self.signable_nodes = set() def __fdt_list(self, path): - return util.run_and_log(self.cons, f'fdtget -l {self.fit} {path}') + return utils.run_and_log(self.cons, f'fdtget -l {self.fit} {path}') def __fdt_set(self, node, **prop_value): for prop, value in prop_value.items(): - util.run_and_log(self.cons, f'fdtput -ts {self.fit} {node} {prop} {value}') + utils.run_and_log(self.cons, + f'fdtput -ts {self.fit} {node} {prop} {value}') def __fdt_get_binary(self, node, prop): - numbers = util.run_and_log(self.cons, f'fdtget -tbi {self.fit} {node} {prop}') + numbers = utils.run_and_log(self.cons, + f'fdtget -tbi {self.fit} {node} {prop}') bignum = bytearray() for little_num in numbers.split(): @@ -53,7 +55,7 @@ class SignableFitImage(object): self.__fdt_set(f'{image}/signature', algo='sha256,ecdsa256') def sign(self, mkimage, key_file): - util.run_and_log(self.cons, [mkimage, '-F', self.fit, f'-G{key_file}']) + utils.run_and_log(self.cons, [mkimage, '-F', self.fit, f'-G{key_file}']) def check_signatures(self, key): for image in self.signable_nodes: @@ -76,11 +78,11 @@ def test_fit_ecdsa(ubman): def assemble_fit_image(dest_fit, its, destdir): dtc_args = f'-I dts -O dtb -i {destdir}' - util.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) + utils.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) def dtc(dts): dtb = dts.replace('.dts', '.dtb') - util.run_and_log(cons, f'dtc {datadir}/{dts} -O dtb -o {tempdir}/{dtb}') + utils.run_and_log(cons, f'dtc {datadir}/{dts} -O dtb -o {tempdir}/{dtb}') cons = ubman mkimage = cons.config.build_dir + '/tools/mkimage' diff --git a/test/py/tests/test_fit_hashes.py b/test/py/tests/test_fit_hashes.py index 0b3c85f8e23..bcde045d6c8 100644 --- a/test/py/tests/test_fit_hashes.py +++ b/test/py/tests/test_fit_hashes.py @@ -12,7 +12,7 @@ This test doesn't run the sandbox. It only checks the host tool 'mkimage' import os import pytest -import utils as util +import utils kernel_hashes = { "sha512" : "f18c1486a2c29f56360301576cdfce4dfd8e8e932d0ed8e239a1f314b8ae1d77b2a58cd7fe32e4075e69448e623ce53b0b6aa6ce5626d2c189a5beae29a68d93", @@ -32,14 +32,15 @@ class ReadonlyFitImage(object): self.hashable_nodes = set() def __fdt_list(self, path): - return util.run_and_log(self.cons, f'fdtget -l {self.fit} {path}') + return utils.run_and_log(self.cons, f'fdtget -l {self.fit} {path}') def __fdt_get(self, node, prop): - val = util.run_and_log(self.cons, f'fdtget {self.fit} {node} {prop}') + val = utils.run_and_log(self.cons, f'fdtget {self.fit} {node} {prop}') return val.rstrip('\n') def __fdt_get_sexadecimal(self, node, prop): - numbers = util.run_and_log(self.cons, f'fdtget -tbx {self.fit} {node} {prop}') + numbers = utils.run_and_log(self.cons, + f'fdtget -tbx {self.fit} {node} {prop}') sexadecimal = '' for num in numbers.rstrip('\n').split(' '): @@ -85,11 +86,12 @@ def test_mkimage_hashes(ubman): def assemble_fit_image(dest_fit, its, destdir): dtc_args = f'-I dts -O dtb -i {destdir}' - util.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) + utils.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) def dtc(dts): dtb = dts.replace('.dts', '.dtb') - util.run_and_log(cons, f'dtc {datadir}/{dts} -O dtb -o {tempdir}/{dtb}') + utils.run_and_log(cons, + f'dtc {datadir}/{dts} -O dtb -o {tempdir}/{dtb}') cons = ubman mkimage = cons.config.build_dir + '/tools/mkimage' diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py index 5b259796ebe..47a584ffe7c 100644 --- a/test/py/tests/test_fs/conftest.py +++ b/test/py/tests/test_fs/conftest.py @@ -8,7 +8,6 @@ import pytest import re from subprocess import call, check_call, check_output, CalledProcessError from fstest_defs import * -import utils as util # pylint: disable=E0611 from tests import fs_helper diff --git a/test/py/tests/test_kconfig.py b/test/py/tests/test_kconfig.py index b4a28ec7a5a..a3796ea7e47 100644 --- a/test/py/tests/test_kconfig.py +++ b/test/py/tests/test_kconfig.py @@ -4,7 +4,7 @@ import pytest -import utils as util +import utils # This is needed for Azure, since the default '..' directory is not writeable TMPDIR = '/tmp/test_kconfig' @@ -16,7 +16,7 @@ def test_kconfig(ubman): cons = ubman # This detects build errors in test/lib/kconfig.c - out = util.run_and_log( + out = utils.run_and_log( cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox', '-a', 'TEST_KCONFIG', '-o', TMPDIR], ignore_errors=True) assert 'invalid_use_of_IF_ENABLED_INT' in out @@ -29,7 +29,7 @@ def test_kconfig_spl(ubman): cons = ubman # This detects build errors in test/lib/kconfig_spl.c - out = util.run_and_log( + out = utils.run_and_log( cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox_spl', '-a', 'TEST_KCONFIG', '-o', TMPDIR], ignore_errors=True) assert 'invalid_use_of_IF_ENABLED_INT' in out diff --git a/test/py/tests/test_of_migrate.py b/test/py/tests/test_of_migrate.py index 1692cbc48bb..e866eebbfd4 100644 --- a/test/py/tests/test_of_migrate.py +++ b/test/py/tests/test_of_migrate.py @@ -7,7 +7,7 @@ import os import pytest -import utils as util +import utils # This is needed for Azure, since the default '..' directory is not writeable TMPDIR1 = '/tmp/test_no_migrate' @@ -33,8 +33,8 @@ def build_for_migrate(cons, replace_pair, board, tmpdir, disable_migrate=True): dt_dir = os.path.join(build_dir, 'arch', 'sandbox', 'dts') orig_fname = os.path.join(dt_dir, 'sandbox.dtb') out_dts = os.path.join(dt_dir, 'sandbox_out.dts') - util.run_and_log(cons, ['dtc', orig_fname, '-I', 'dtb', '-O', 'dts', - '-o', out_dts]) + utils.run_and_log(cons, ['dtc', orig_fname, '-I', 'dtb', '-O', 'dts', + '-o', out_dts]) # Update it to use an old tag with open(out_dts) as inf: @@ -45,7 +45,7 @@ def build_for_migrate(cons, replace_pair, board, tmpdir, disable_migrate=True): with open(dts_fname, 'w') as outf: print(data, file=outf) dtb_fname = os.path.join(dt_dir, 'sandbox_oldtag.dtb') - util.run_and_log(cons, ['dtc', dts_fname, '-o', dtb_fname]) + utils.run_and_log(cons, ['dtc', dts_fname, '-o', dtb_fname]) migrate = ['-a', '~CONFIG_OF_TAG_MIGRATE'] if disable_migrate else [] @@ -54,7 +54,7 @@ def build_for_migrate(cons, replace_pair, board, tmpdir, disable_migrate=True): env['EXT_DTB'] = dtb_fname env['DEVICE_TREE'] = 'sandbox_new' env['NO_LTO'] = '1' # Speed up build - out = util.run_and_log( + out = utils.run_and_log( cons, ['./tools/buildman/buildman', '-m', '--board', board, *migrate, '-w', '-o', tmpdir], ignore_errors=True, env=env) return out @@ -70,7 +70,7 @@ def test_of_no_migrate(ubman): # It should fail to run, since the lcd device will not be bound before # relocation. so won't get its frame-buffer memory - out = util.run_and_log( + out = utils.run_and_log( cons, [os.path.join(TMPDIR1, 'u-boot'), '-D', '-c', 'help'], ignore_errors=True) assert "Video device 'lcd' cannot allocate frame buffer memory" in out @@ -102,7 +102,7 @@ def test_of_migrate(ubman): 'sandbox', TMPDIR3, disable_migrate=False) # It should show a migration message - out = util.run_and_log( + out = utils.run_and_log( cons, [os.path.join(TMPDIR3, 'u-boot'), '-D', '-c', 'help'], ignore_errors=True) assert "Warning: Device tree includes old 'u-boot,dm-' tags" in out diff --git a/test/py/tests/test_ofplatdata.py b/test/py/tests/test_ofplatdata.py index d414a910d9f..b4d2db03deb 100644 --- a/test/py/tests/test_ofplatdata.py +++ b/test/py/tests/test_ofplatdata.py @@ -2,7 +2,7 @@ # Copyright (c) 2016 Google, Inc import pytest -import utils as util +import utils @pytest.mark.boardspec('sandbox_spl') @pytest.mark.buildconfigspec('spl_of_platdata') @@ -11,7 +11,7 @@ def test_spl_devicetree(ubman): cons = ubman dtb = cons.config.build_dir + '/spl/u-boot-spl.dtb' fdtgrep = cons.config.build_dir + '/tools/fdtgrep' - output = util.run_and_log(cons, [fdtgrep, '-l', dtb]) + output = utils.run_and_log(cons, [fdtgrep, '-l', dtb]) assert "bootph-all" not in output assert "bootph-some-ram" not in output diff --git a/test/py/tests/test_optee_rpmb.py b/test/py/tests/test_optee_rpmb.py index 1ef1c117d27..04b3b5e41ef 100644 --- a/test/py/tests/test_optee_rpmb.py +++ b/test/py/tests/test_optee_rpmb.py @@ -7,7 +7,7 @@ This tests optee_rpmb cmd in U-Boot """ import pytest -import utils as util +import utils @pytest.mark.buildconfigspec('cmd_optee_rpmb') def test_optee_rpmb_read_write(ubman): diff --git a/test/py/tests/test_sandbox_opts.py b/test/py/tests/test_sandbox_opts.py index 16901409172..f50302cbe6b 100644 --- a/test/py/tests/test_sandbox_opts.py +++ b/test/py/tests/test_sandbox_opts.py @@ -4,7 +4,7 @@ import pytest -import utils as util +import utils # This is needed for Azure, since the default '..' directory is not writeable TMPDIR = '/tmp/test_cmdline' @@ -15,7 +15,7 @@ def test_sandbox_cmdline(ubman): """Test building sandbox without CONFIG_CMDLINE""" cons = ubman - out = util.run_and_log( + utils.run_and_log( cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox', '-a', '~CMDLINE', '-o', TMPDIR]) @@ -25,6 +25,6 @@ def test_sandbox_lto(ubman): """Test building sandbox without CONFIG_LTO""" cons = ubman - out = util.run_and_log( + utils.run_and_log( cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox', '-a', '~LTO', '-o', TMPDIR]) diff --git a/test/py/tests/test_scp03.py b/test/py/tests/test_scp03.py index 296d7c7d953..414b4251a69 100644 --- a/test/py/tests/test_scp03.py +++ b/test/py/tests/test_scp03.py @@ -11,7 +11,7 @@ For additional details check doc/usage/scp03.rst """ import pytest -import utils as util +import utils @pytest.mark.buildconfigspec('cmd_scp03') def test_scp03(ubman): diff --git a/test/py/tests/test_source.py b/test/py/tests/test_source.py index 60013e438ba..f0437aa15ca 100644 --- a/test/py/tests/test_source.py +++ b/test/py/tests/test_source.py @@ -3,7 +3,7 @@ import os import pytest -import utils as util +import utils @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_echo') @@ -15,7 +15,7 @@ def test_source(ubman): mkimage = os.path.join(cons.config.build_dir, 'tools/mkimage') its = os.path.join(cons.config.source_dir, 'test/py/tests/source.its') fit = os.path.join(cons.config.build_dir, 'source.itb') - util.run_and_log(cons, (mkimage, '-f', its, fit)) + utils.run_and_log(cons, (mkimage, '-f', its, fit)) cons.run_command(f'host load hostfs - $loadaddr {fit}') assert '2' in cons.run_command('source') diff --git a/test/py/tests/test_trace.py b/test/py/tests/test_trace.py index 6fa4229233b..72f65f2b347 100644 --- a/test/py/tests/test_trace.py +++ b/test/py/tests/test_trace.py @@ -6,7 +6,7 @@ import os import pytest import re -import utils as util +import utils # This is needed for Azure, since the default '..' directory is not writeable TMPDIR = '/tmp/test_trace' @@ -106,12 +106,12 @@ def check_function(cons, fname, proftool, map_fname, trace_dat): map_fname (str): Filename of System.map trace_dat (str): Filename of output file """ - out = util.run_and_log( + out = utils.run_and_log( cons, [proftool, '-t', fname, '-o', trace_dat, '-m', map_fname, 'dump-ftrace']) # Check that trace-cmd can read it - out = util.run_and_log(cons, ['trace-cmd', 'dump', trace_dat]) + out = utils.run_and_log(cons, ['trace-cmd', 'dump', trace_dat]) # Tracing meta data in file /tmp/test_trace/trace.dat: # [Initial format] @@ -140,7 +140,7 @@ def check_function(cons, fname, proftool, map_fname, trace_dat): # Check that the trace has something useful cmd = f"trace-cmd report -l {trace_dat} |grep -E '(initf_|initr_)'" - out = util.run_and_log(cons, ['sh', '-c', cmd]) + out = utils.run_and_log(cons, ['sh', '-c', cmd]) # Format: # u-boot-1 0..... 60.805596: function: initf_malloc @@ -182,13 +182,13 @@ def check_funcgraph(cons, fname, proftool, map_fname, trace_dat): """ # Generate the funcgraph format - out = util.run_and_log( + out = utils.run_and_log( cons, [proftool, '-t', fname, '-o', trace_dat, '-m', map_fname, 'dump-ftrace', '-f', 'funcgraph']) # Check that the trace has what we expect cmd = f'trace-cmd report -l {trace_dat} |head -n 70' - out = util.run_and_log(cons, ['sh', '-c', cmd]) + out = utils.run_and_log(cons, ['sh', '-c', cmd]) # First look for this: # u-boot-1 0..... 282.101360: funcgraph_entry: 0.004 us | initf_malloc(); @@ -230,7 +230,7 @@ def check_funcgraph(cons, fname, proftool, map_fname, trace_dat): # Now look for initf_dm() and dm_timer_init() so we can check the bootstage # time cmd = f"trace-cmd report -l {trace_dat} |grep -E '(initf_dm|dm_timer_init)'" - out = util.run_and_log(cons, ['sh', '-c', cmd]) + out = utils.run_and_log(cons, ['sh', '-c', cmd]) start_timestamp = None end_timestamp = None @@ -267,7 +267,7 @@ def check_flamegraph(cons, fname, proftool, map_fname, trace_fg): """ # Generate the flamegraph format - out = util.run_and_log( + out = utils.run_and_log( cons, [proftool, '-t', fname, '-o', trace_fg, '-m', map_fname, 'dump-flamegraph']) @@ -284,7 +284,7 @@ def check_flamegraph(cons, fname, proftool, map_fname, trace_fg): assert found == 2 # Generate the timing graph - out = util.run_and_log( + utils.run_and_log( cons, [proftool, '-t', fname, '-o', trace_fg, '-m', map_fname, 'dump-flamegraph', '-f', 'timing']) diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py index 691c6e6b839..2b29871b7d4 100644 --- a/test/py/tests/test_vboot.py +++ b/test/py/tests/test_vboot.py @@ -42,7 +42,7 @@ import os import shutil import struct import pytest -import utils as util +import utils import vboot_forge import vboot_evil @@ -62,8 +62,8 @@ def dtc(dts, cons, dtc_args, datadir, tmpdir, dtb): dtb: Resulting DTB file. """ dtb = dts.replace('.dts', '.dtb') - util.run_and_log(cons, 'dtc %s %s%s -O dtb ' - '-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb)) + utils.run_and_log(cons, 'dtc %s %s%s -O dtb ' + '-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb)) def make_fit(its, cons, mkimage, dtc_args, datadir, fit): """Make a new FIT from the .its source file. @@ -78,8 +78,8 @@ def make_fit(its, cons, mkimage, dtc_args, datadir, fit): datadir: Path to data directory. fit: Resulting FIT file. """ - util.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', - '%s%s' % (datadir, its), fit]) + utils.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', + '%s%s' % (datadir, its), fit]) # Only run the full suite on a few combinations, since it doesn't add any more # test coverage. @@ -134,8 +134,8 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, options: Options provided to the compiler. """ dtb = dts.replace('.dts', '.dtb') - util.run_and_log(cons, 'dtc %s %s%s -O dtb ' - '-o %s%s %s' % (dtc_args, datadir, dts, tmpdir, dtb, options)) + utils.run_and_log(cons, 'dtc %s %s%s -O dtb -o %s%s %s' % + (dtc_args, datadir, dts, tmpdir, dtb, options)) def run_binman(dtb): """Run binman to build an image @@ -145,9 +145,9 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, """ pythonpath = os.environ.get('PYTHONPATH', '') os.environ['PYTHONPATH'] = pythonpath + ':' + '%s/../scripts/dtc/pylibfdt' % tmpdir - util.run_and_log(cons, [binman, 'build', '-d', "%s/%s" % (tmpdir,dtb), - '-a', "pre-load-key-path=%s" % tmpdir, '-O', - tmpdir, '-I', tmpdir]) + utils.run_and_log(cons, [binman, 'build', '-d', "%s/%s" % (tmpdir,dtb), + '-a', "pre-load-key-path=%s" % tmpdir, '-O', + tmpdir, '-I', tmpdir]) os.environ['PYTHONPATH'] = pythonpath def run_bootm(sha_algo, test_type, expect_string, boots, fit=None): @@ -195,7 +195,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, if options: args += options.split(' ') cons.log.action('%s: Sign images' % sha_algo) - util.run_and_log(cons, args) + utils.run_and_log(cons, args) def sign_fit_dtb(sha_algo, options, dtb): """Sign the FIT @@ -212,7 +212,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, if options: args += options.split(' ') cons.log.action('%s: Sign images' % sha_algo) - util.run_and_log(cons, args) + utils.run_and_log(cons, args) def sign_fit_norequire(sha_algo, options): """Sign the FIT @@ -229,7 +229,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, if options: args += options.split(' ') cons.log.action('%s: Sign images' % sha_algo) - util.run_and_log(cons, args) + utils.run_and_log(cons, args) def replace_fit_totalsize(size): """Replace FIT header's totalsize with something greater. @@ -278,14 +278,14 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, else: rsa_keygen_bits = 2048 - util.run_and_log(cons, 'openssl genpkey -algorithm RSA -out %s%s.key ' + utils.run_and_log(cons, 'openssl genpkey -algorithm RSA -out %s%s.key ' '-pkeyopt rsa_keygen_bits:%d ' '-pkeyopt rsa_keygen_pubexp:%d' % (tmpdir, name, rsa_keygen_bits, public_exponent)) # Create a certificate containing the public key - util.run_and_log(cons, 'openssl req -batch -new -x509 -key %s%s.key ' - '-out %s%s.crt' % (tmpdir, name, tmpdir, name)) + utils.run_and_log(cons, 'openssl req -batch -new -x509 -key %s%s.key ' + '-out %s%s.crt' % (tmpdir, name, tmpdir, name)) def test_with_algo(sha_algo, padding, sign_options): """Test verified boot with the given hash algorithm. @@ -328,7 +328,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, cons.log.action('%s: Check signed config on the host' % sha_algo) - util.run_and_log(cons, [fit_check_sign, '-f', fit, '-k', dtb]) + utils.run_and_log(cons, [fit_check_sign, '-f', fit, '-k', dtb]) if full_test: # Make sure that U-Boot checks that the config is in the list of @@ -340,7 +340,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, root, strblock = vboot_forge.manipulate(root, strblock) with open(ffit, 'w+b') as fd: vboot_forge.write_fdt(root, strblock, fd) - util.run_and_log_expect_exception( + utils.run_and_log_expect_exception( cons, [fit_check_sign, '-f', ffit, '-k', dtb], 1, 'Failed to verify required signature') @@ -351,7 +351,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, shutil.copyfile(fit, efit) vboot_evil.add_evil_node(fit, efit, evil_kernel, 'fakeroot') - util.run_and_log_expect_exception( + utils.run_and_log_expect_exception( cons, [fit_check_sign, '-f', efit, '-k', dtb], 1, 'Failed to verify required signature') run_bootm(sha_algo, 'evil fakeroot', 'Bad FIT kernel image format', @@ -363,7 +363,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, vboot_evil.add_evil_node(fit, efit, evil_kernel, 'kernel@') msg = 'Signature checking prevents use of unit addresses (@) in nodes' - util.run_and_log_expect_exception( + utils.run_and_log_expect_exception( cons, [fit_check_sign, '-f', efit, '-k', dtb], 1, msg) run_bootm(sha_algo, 'evil kernel@', msg, False, efit) @@ -384,20 +384,20 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, cons.log.action('%s: Check default FIT header totalsize' % sha_algo) # Increment the first byte of the signature, which should cause failure - sig = util.run_and_log(cons, 'fdtget -t bx %s %s value' % - (fit, sig_node)) + sig = utils.run_and_log(cons, 'fdtget -t bx %s %s value' % + (fit, sig_node)) byte_list = sig.split() byte = int(byte_list[0], 16) byte_list[0] = '%x' % (byte + 1) sig = ' '.join(byte_list) - util.run_and_log(cons, 'fdtput -t bx %s %s value %s' % - (fit, sig_node, sig)) + utils.run_and_log(cons, 'fdtput -t bx %s %s value %s' % + (fit, sig_node, sig)) run_bootm(sha_algo, 'Signed config with bad hash', 'Bad Data Hash', False) cons.log.action('%s: Check bad config on the host' % sha_algo) - util.run_and_log_expect_exception( + utils.run_and_log_expect_exception( cons, [fit_check_sign, '-f', fit, '-k', dtb], 1, 'Failed to verify required signature') @@ -449,8 +449,8 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, # a dev signature only (sign_fit() overwrites the FIT). # Try to boot the FIT with dev key. This FIT should be accepted by # U-Boot because the dev key is required and policy is "any" required key. - util.run_and_log(cons, 'fdtput -t s %s /signature required-mode any' % - (dtb)) + utils.run_and_log(cons, 'fdtput -t s %s /signature required-mode any' % + dtb) run_bootm(sha_algo, 'multi required key', 'dev+', True) # Set the required-mode policy to "all". @@ -459,8 +459,8 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, # a dev signature only (sign_fit() overwrites the FIT). # Try to boot the FIT with dev key. This FIT should not be accepted by # U-Boot because the prod key is required and policy is "all" required key - util.run_and_log(cons, 'fdtput -t s %s /signature required-mode all' % - (dtb)) + utils.run_and_log(cons, 'fdtput -t s %s /signature required-mode all' % + dtb) run_bootm(sha_algo, 'multi required key', '', False) def test_global_sign(sha_algo, padding, sign_options): @@ -594,7 +594,7 @@ def test_fdt_add_pubkey(ubman, name, sha_algo, padding, sign_options, algo_arg): if options: args += options.split(' ') cons.log.action('%s: Sign images' % sha_algo) - util.run_and_log(cons, args) + utils.run_and_log(cons, args) def test_add_pubkey(sha_algo, padding, sign_options): """Test fdt_add_pubkey utility with given hash algorithm and padding. @@ -613,9 +613,11 @@ def test_fdt_add_pubkey(ubman, name, sha_algo, padding, sign_options, algo_arg): cons.log.action('%s: Test fdt_add_pubkey with signed configuration' % sha_algo) # Then add the dev key via the fdt_add_pubkey tool - util.run_and_log(cons, [fdt_add_pubkey, '-a', '%s,%s' % ('sha256' if algo_arg else sha_algo, \ - 'rsa3072' if sha_algo == 'sha384' else 'rsa2048'), - '-k', tmpdir, '-n', 'dev', '-r', 'conf', dtb]) + utils.run_and_log(cons, + [fdt_add_pubkey, '-a', '%s,%s' % + ('sha256' if algo_arg else sha_algo, + 'rsa3072' if sha_algo == 'sha384' else 'rsa2048'), + '-k', tmpdir, '-n', 'dev', '-r', 'conf', dtb]) make_fit('sign-configs-%s%s.its' % (sha_algo, padding), cons, mkimage, dtc_args, datadir, fit) @@ -623,7 +625,7 @@ def test_fdt_add_pubkey(ubman, name, sha_algo, padding, sign_options, algo_arg): sign_fit(sha_algo, sign_options) # Check with fit_check_sign that FIT is signed with key - util.run_and_log(cons, [fit_check_sign, '-f', fit, '-k', dtb]) + utils.run_and_log(cons, [fit_check_sign, '-f', fit, '-k', dtb]) cons = ubman tmpdir = os.path.join(cons.config.result_dir, name) + '/' -- cgit v1.3.1 From d08653d3699c1aafada3418c9f74b887bfb21a65 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 9 Feb 2025 09:07:17 -0700 Subject: test/py: Drop assigning ubman to cons Now that we have a shorter name, we don't need this sort of thing. Just use ubman instead. Signed-off-by: Simon Glass --- test/py/tests/test_android/test_abootimg.py | 43 ++++---- test/py/tests/test_efi_fit.py | 81 +++++++------- test/py/tests/test_env.py | 12 +-- test/py/tests/test_event_dump.py | 5 +- test/py/tests/test_fit.py | 63 ++++++----- test/py/tests/test_fit_auto_signed.py | 27 +++-- test/py/tests/test_fit_ecdsa.py | 25 +++-- test/py/tests/test_fit_hashes.py | 23 ++-- test/py/tests/test_handoff.py | 3 +- test/py/tests/test_help.py | 14 ++- test/py/tests/test_kconfig.py | 6 +- test/py/tests/test_log.py | 14 ++- test/py/tests/test_mmc.py | 8 +- test/py/tests/test_of_migrate.py | 27 +++-- test/py/tests/test_ofplatdata.py | 7 +- test/py/tests/test_sandbox_opts.py | 6 +- test/py/tests/test_source.py | 41 ++++---- test/py/tests/test_spl.py | 5 +- test/py/tests/test_suite.py | 67 ++++++------ test/py/tests/test_tpm2.py | 4 +- test/py/tests/test_trace.py | 69 ++++++------ test/py/tests/test_upl.py | 11 +- test/py/tests/test_ut.py | 158 ++++++++++++++-------------- test/py/tests/test_vbe.py | 15 ++- test/py/tests/test_vbe_vpl.py | 21 ++-- test/py/tests/test_vboot.py | 146 +++++++++++++------------ test/py/tests/test_vpl.py | 5 +- 27 files changed, 437 insertions(+), 469 deletions(-) (limited to 'test/py/tests/test_android') diff --git a/test/py/tests/test_android/test_abootimg.py b/test/py/tests/test_android/test_abootimg.py index c31fb466ec7..2aadb692b30 100644 --- a/test/py/tests/test_android/test_abootimg.py +++ b/test/py/tests/test_android/test_abootimg.py @@ -232,38 +232,37 @@ def test_abootimg(abootimg_disk_image, ubman): def test_abootimgv4(abootimgv4_disk_image_vboot, abootimgv4_disk_image_boot, ubman): """Test the 'abootimg' command with boot image header v4.""" - cons = ubman - cons.log.action('Loading disk image to RAM...') - cons.run_command('setenv loadaddr 0x%x' % (loadaddr)) - cons.run_command('setenv vloadaddr 0x%x' % (vloadaddr)) - cons.run_command('host load hostfs - 0x%x %s' % (vloadaddr, + ubman.log.action('Loading disk image to RAM...') + ubman.run_command('setenv loadaddr 0x%x' % (loadaddr)) + ubman.run_command('setenv vloadaddr 0x%x' % (vloadaddr)) + ubman.run_command('host load hostfs - 0x%x %s' % (vloadaddr, abootimgv4_disk_image_vboot.path)) - cons.run_command('host load hostfs - 0x%x %s' % (loadaddr, + ubman.run_command('host load hostfs - 0x%x %s' % (loadaddr, abootimgv4_disk_image_boot.path)) - cons.run_command('abootimg addr 0x%x 0x%x' % (loadaddr, vloadaddr)) - cons.log.action('Testing \'abootimg get ver\'...') - response = cons.run_command('abootimg get ver') + ubman.run_command('abootimg addr 0x%x 0x%x' % (loadaddr, vloadaddr)) + ubman.log.action('Testing \'abootimg get ver\'...') + response = ubman.run_command('abootimg get ver') assert response == "4" - cons.run_command('abootimg get ver v') - response = cons.run_command('env print v') + ubman.run_command('abootimg get ver v') + response = ubman.run_command('env print v') assert response == 'v=4' - cons.log.action('Testing \'abootimg get recovery_dtbo\'...') - response = cons.run_command('abootimg get recovery_dtbo a') + ubman.log.action('Testing \'abootimg get recovery_dtbo\'...') + response = ubman.run_command('abootimg get recovery_dtbo a') assert response == 'Error: header version must be >= 1 and <= 2 to get dtbo' - cons.log.action('Testing \'abootimg get dtb_load_addr\'...') - cons.run_command('abootimg get dtb_load_addr a') - response = cons.run_command('env print a') + ubman.log.action('Testing \'abootimg get dtb_load_addr\'...') + ubman.run_command('abootimg get dtb_load_addr a') + response = ubman.run_command('env print a') assert response == 'a=11f00000' - cons.log.action('Testing \'abootimg get dtb --index\'...') - cons.run_command('abootimg get dtb --index=1 dtb2_start') - response = cons.run_command('env print dtb2_start') + ubman.log.action('Testing \'abootimg get dtb --index\'...') + ubman.run_command('abootimg get dtb --index=1 dtb2_start') + response = ubman.run_command('env print dtb2_start') correct_str = "dtb2_start=%x" % (dtb2_addr) assert response == correct_str - cons.run_command('fdt addr $dtb2_start') - cons.run_command('fdt get value v / model') - response = cons.run_command('env print v') + ubman.run_command('fdt addr $dtb2_start') + ubman.run_command('fdt get value v / model') + response = ubman.run_command('env print v') assert response == 'v=x2' diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py index e7d523a77d5..5f352e7efff 100644 --- a/test/py/tests/test_efi_fit.py +++ b/test/py/tests/test_efi_fit.py @@ -148,13 +148,13 @@ def test_efi_fit_launch(ubman): at the beginning of this file. """ - init_usb = cons.config.env.get('env__net_uses_usb', False) + init_usb = ubman.config.env.get('env__net_uses_usb', False) if init_usb: - cons.run_command('usb start') + ubman.run_command('usb start') - init_pci = cons.config.env.get('env__net_uses_pci', False) + init_pci = ubman.config.env.get('env__net_uses_pci', False) if init_pci: - cons.run_command('pci enum') + ubman.run_command('pci enum') def net_dhcp(): """Execute the dhcp command. @@ -163,18 +163,18 @@ def test_efi_fit_launch(ubman): comment at the beginning of this file. """ - has_dhcp = cons.config.buildconfig.get('config_cmd_dhcp', 'n') == 'y' + has_dhcp = ubman.config.buildconfig.get('config_cmd_dhcp', 'n') == 'y' if not has_dhcp: - cons.log.warning('CONFIG_CMD_DHCP != y: Skipping DHCP network setup') + ubman.log.warning('CONFIG_CMD_DHCP != y: Skipping DHCP network setup') return False - test_dhcp = cons.config.env.get('env__net_dhcp_server', False) + test_dhcp = ubman.config.env.get('env__net_dhcp_server', False) if not test_dhcp: - cons.log.info('No DHCP server available') + ubman.log.info('No DHCP server available') return False - cons.run_command('setenv autoload no') - output = cons.run_command('dhcp') + ubman.run_command('setenv autoload no') + output = ubman.run_command('dhcp') assert 'DHCP client bound to address ' in output return True @@ -185,18 +185,18 @@ def test_efi_fit_launch(ubman): the beginning of this file. """ - has_dhcp = cons.config.buildconfig.get('config_cmd_dhcp', 'n') == 'y' + has_dhcp = ubman.config.buildconfig.get('config_cmd_dhcp', 'n') == 'y' if not has_dhcp: - cons.log.warning('CONFIG_NET != y: Skipping static network setup') + ubman.log.warning('CONFIG_NET != y: Skipping static network setup') return False - env_vars = cons.config.env.get('env__net_static_env_vars', None) + env_vars = ubman.config.env.get('env__net_static_env_vars', None) if not env_vars: - cons.log.info('No static network configuration is defined') + ubman.log.info('No static network configuration is defined') return False for (var, val) in env_vars: - cons.run_command('setenv %s %s' % (var, val)) + ubman.run_command('setenv %s %s' % (var, val)) return True def make_fpath(file_name): @@ -208,7 +208,7 @@ def test_efi_fit_launch(ubman): The computed file path. """ - return os.path.join(cons.config.build_dir, file_name) + return os.path.join(ubman.config.build_dir, file_name) def make_efi(fname, comp): """Create an UEFI binary. @@ -224,11 +224,11 @@ def test_efi_fit_launch(ubman): """ bin_path = make_fpath(fname) - utils.run_and_log(cons, + utils.run_and_log(ubman, ['cp', make_fpath('lib/efi_loader/helloworld.efi'), bin_path]) if comp: - utils.run_and_log(cons, ['gzip', '-f', bin_path]) + utils.run_and_log(ubman, ['gzip', '-f', bin_path]) bin_path += '.gz' return bin_path @@ -257,10 +257,10 @@ def test_efi_fit_launch(ubman): # Build the test FDT. dtb = make_fpath('test-efi-fit-%s.dtb' % fdt_type) - utils.run_and_log(cons, + utils.run_and_log(ubman, ['dtc', '-I', 'dts', '-O', 'dtb', '-o', dtb, dts]) if comp: - utils.run_and_log(cons, ['gzip', '-f', dtb]) + utils.run_and_log(ubman, ['gzip', '-f', dtb]) dtb += '.gz' return dtb @@ -292,7 +292,7 @@ def test_efi_fit_launch(ubman): # Build the test ITS. fit_path = make_fpath('test-efi-fit-helloworld.fit') utils.run_and_log( - cons, [make_fpath('tools/mkimage'), '-f', its_path, fit_path]) + ubman, [make_fpath('tools/mkimage'), '-f', its_path, fit_path]) return fit_path def load_fit_from_host(fit): @@ -308,9 +308,9 @@ def test_efi_fit_launch(ubman): addr = fit.get('addr', None) if not addr: - addr = utils.find_ram_base(cons) + addr = utils.find_ram_base(ubman) - output = cons.run_command( + output = ubman.run_command( 'host load hostfs - %x %s/%s' % (addr, fit['dn'], fit['fn'])) expected_text = ' bytes read' size = fit.get('size', None) @@ -335,10 +335,10 @@ def test_efi_fit_launch(ubman): addr = fit.get('addr', None) if not addr: - addr = utils.find_ram_base(cons) + addr = utils.find_ram_base(ubman) file_name = fit['fn'] - output = cons.run_command('tftpboot %x %s' % (addr, file_name)) + output = ubman.run_command('tftpboot %x %s' % (addr, file_name)) expected_text = 'Bytes transferred = ' size = fit.get('size', None) if size: @@ -349,10 +349,10 @@ def test_efi_fit_launch(ubman): if not expected_crc: return addr - if cons.config.buildconfig.get('config_cmd_crc32', 'n') != 'y': + if ubman.config.buildconfig.get('config_cmd_crc32', 'n') != 'y': return addr - output = cons.run_command('crc32 $fileaddr $filesize') + output = ubman.run_command('crc32 $fileaddr $filesize') assert expected_crc in output return addr @@ -384,10 +384,10 @@ def test_efi_fit_launch(ubman): generated content. """ - with cons.log.section('FDT=%s;COMP=%s' % (enable_fdt, enable_comp)): + with ubman.log.section('FDT=%s;COMP=%s' % (enable_fdt, enable_comp)): if is_sandbox: fit = { - 'dn': cons.config.build_dir, + 'dn': ubman.config.build_dir, } else: # Init networking. @@ -397,7 +397,7 @@ def test_efi_fit_launch(ubman): if not net_set_up: pytest.skip('Network not initialized') - fit = cons.config.env.get('env__efi_fit_tftp_file', None) + fit = ubman.config.env.get('env__efi_fit_tftp_file', None) if not fit: pytest.skip('No env__efi_fit_tftp_file binary specified in environment') @@ -412,8 +412,8 @@ def test_efi_fit_launch(ubman): fit['size'] = os.path.getsize(fit_path) # Copy image to TFTP root directory. - if fit['dn'] != cons.config.build_dir: - utils.run_and_log(cons, + if fit['dn'] != ubman.config.build_dir: + utils.run_and_log(ubman, ['mv', '-f', fit_path, '%s/' % fit['dn']]) # Load FIT image. @@ -423,31 +423,30 @@ def test_efi_fit_launch(ubman): fit_config = 'config-efi-fdt' if enable_fdt else 'config-efi-nofdt' # Try booting. - output = cons.run_command('bootm %x#%s' % (addr, fit_config)) + output = ubman.run_command('bootm %x#%s' % (addr, fit_config)) if enable_fdt: assert 'Booting using the fdt blob' in output assert 'Hello, world' in output assert '## Application failed' not in output - cons.restart_uboot() + ubman.restart_uboot() - cons = ubman # Array slice removes leading/trailing quotes. - sys_arch = cons.config.buildconfig.get('config_sys_arch', '"sandbox"')[1:-1] + sys_arch = ubman.config.buildconfig.get('config_sys_arch', '"sandbox"')[1:-1] if sys_arch == 'arm': - arm64 = cons.config.buildconfig.get('config_arm64') + arm64 = ubman.config.buildconfig.get('config_arm64') if arm64: sys_arch = 'arm64' is_sandbox = sys_arch == 'sandbox' if is_sandbox: - old_dtb = cons.config.dtb + old_dtb = ubman.config.dtb try: if is_sandbox: # Use our own device tree file, will be restored afterwards. control_dtb = make_dtb('internal', False) - cons.config.dtb = control_dtb + ubman.config.dtb = control_dtb # Run tests # - fdt OFF, gzip OFF @@ -464,5 +463,5 @@ def test_efi_fit_launch(ubman): finally: if is_sandbox: # Go back to the original U-Boot with the correct dtb. - cons.config.dtb = old_dtb - cons.restart_uboot() + ubman.config.dtb = old_dtb + ubman.restart_uboot() diff --git a/test/py/tests/test_env.py b/test/py/tests/test_env.py index 376ea7b78b8..383e26c03b0 100644 --- a/test/py/tests/test_env.py +++ b/test/py/tests/test_env.py @@ -177,9 +177,8 @@ def validate_set(state_test_env, var, value): @pytest.mark.boardspec('sandbox') def test_env_initial_env_file(ubman): """Test that the u-boot-initial-env make target works""" - cons = ubman - builddir = 'O=' + cons.config.build_dir - envfile = cons.config.build_dir + '/u-boot-initial-env' + builddir = 'O=' + ubman.config.build_dir + envfile = ubman.config.build_dir + '/u-boot-initial-env' # remove if already exists from an older run try: @@ -187,7 +186,7 @@ def test_env_initial_env_file(ubman): except: pass - utils.run_and_log(cons, ['make', builddir, 'u-boot-initial-env']) + utils.run_and_log(ubman, ['make', builddir, 'u-boot-initial-env']) assert os.path.exists(envfile) @@ -560,15 +559,14 @@ def test_env_text(ubman): fname = os.path.join(path, 'infile') with open(fname, 'w') as inf: print(intext, file=inf) - result = utils.run_and_log(cons, ['awk', '-f', script, fname]) + result = utils.run_and_log(ubman, ['awk', '-f', script, fname]) if expect_val is not None: expect = '#define CONFIG_EXTRA_ENV_TEXT "%s"\n' % expect_val assert result == expect else: assert result == '' - cons = ubman - script = os.path.join(cons.config.source_dir, 'scripts', 'env2string.awk') + script = os.path.join(ubman.config.source_dir, 'scripts', 'env2string.awk') # simple script with a single var check_script('fred=123', 'fred=123\\0') diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py index 8297663fbff..b9d48f54dc2 100644 --- a/test/py/tests/test_event_dump.py +++ b/test/py/tests/test_event_dump.py @@ -11,9 +11,8 @@ import utils @pytest.mark.boardspec('sandbox') def test_event_dump(ubman): """Test that the "help" command can be executed.""" - cons = ubman - sandbox = cons.config.build_dir + '/u-boot' - out = utils.run_and_log(cons, ['scripts/event_dump.py', sandbox]) + sandbox = ubman.config.build_dir + '/u-boot' + out = utils.run_and_log(ubman, ['scripts/event_dump.py', sandbox]) expect = '''.*Event type Id Source location -------------------- ------------------------------ ------------------------------ EVT_FT_FIXUP bootmeth_vbe_ft_fixup .*boot/vbe_request.c:.* diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index bfc20c4b1ed..619f73153a0 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -127,7 +127,7 @@ def test_fit(ubman): Return: Temporary filename """ - return os.path.join(cons.config.build_dir, leaf) + return os.path.join(ubman.config.build_dir, leaf) def filesize(fname): """Get the size of a file @@ -165,7 +165,7 @@ def test_fit(ubman): return fname def make_compressed(filename): - utils.run_and_log(cons, ['gzip', '-f', '-k', filename]) + utils.run_and_log(ubman, ['gzip', '-f', '-k', filename]) return filename + '.gz' def find_matching(text, match): @@ -260,10 +260,10 @@ def test_fit(ubman): - run code coverage to make sure we are testing all the code """ # Set up invariant files - control_dtb = fit_util.make_dtb(cons, base_fdt, 'u-boot') - kernel = fit_util.make_kernel(cons, 'test-kernel.bin', 'kernel') + control_dtb = fit_util.make_dtb(ubman, base_fdt, 'u-boot') + kernel = fit_util.make_kernel(ubman, 'test-kernel.bin', 'kernel') ramdisk = make_ramdisk('test-ramdisk.bin', 'ramdisk') - loadables1 = fit_util.make_kernel(cons, 'test-loadables1.bin', 'lenrek') + loadables1 = fit_util.make_kernel(ubman, 'test-loadables1.bin', 'lenrek') loadables2 = make_ramdisk('test-loadables2.bin', 'ksidmar') kernel_out = make_fname('kernel-out.bin') fdt = make_fname('u-boot.dtb') @@ -311,16 +311,16 @@ def test_fit(ubman): } # Make a basic FIT and a script to load it - fit = fit_util.make_fit(cons, mkimage, base_its, params) + fit = fit_util.make_fit(ubman, mkimage, base_its, params) params['fit'] = fit cmd = base_script % params # First check that we can load a kernel # We could perhaps reduce duplication with some loss of readability - cons.config.dtb = control_dtb - cons.restart_uboot() - with cons.log.section('Kernel load'): - output = cons.run_command_list(cmd.splitlines()) + ubman.config.dtb = control_dtb + ubman.restart_uboot() + with ubman.log.section('Kernel load'): + output = ubman.run_command_list(cmd.splitlines()) check_equal(kernel, kernel_out, 'Kernel not loaded') check_not_equal(control_dtb, fdt_out, 'FDT loaded but should be ignored') @@ -340,7 +340,7 @@ def test_fit(ubman): (fit_offset, real_fit_offset)) # Check if bootargs strings substitution works - output = cons.run_command_list([ + output = ubman.run_command_list([ 'env set bootargs \\\"\'my_boot_var=${foo}\'\\\"', 'env set foo bar', 'bootm prep', @@ -348,63 +348,62 @@ def test_fit(ubman): assert 'bootargs="my_boot_var=bar"' in output, "Bootargs strings not substituted" # Now a kernel and an FDT - with cons.log.section('Kernel + FDT load'): + with ubman.log.section('Kernel + FDT load'): params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr'] - fit = fit_util.make_fit(cons, mkimage, base_its, params) - cons.restart_uboot() - output = cons.run_command_list(cmd.splitlines()) + fit = fit_util.make_fit(ubman, mkimage, base_its, params) + ubman.restart_uboot() + output = ubman.run_command_list(cmd.splitlines()) check_equal(kernel, kernel_out, 'Kernel not loaded') check_equal(control_dtb, fdt_out, 'FDT not loaded') check_not_equal(ramdisk, ramdisk_out, 'Ramdisk loaded but should not be') # Try a ramdisk - with cons.log.section('Kernel + FDT + Ramdisk load'): + with ubman.log.section('Kernel + FDT + Ramdisk load'): params['ramdisk_config'] = 'ramdisk = "ramdisk-1";' params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr'] - fit = fit_util.make_fit(cons, mkimage, base_its, params) - cons.restart_uboot() - output = cons.run_command_list(cmd.splitlines()) + fit = fit_util.make_fit(ubman, mkimage, base_its, params) + ubman.restart_uboot() + output = ubman.run_command_list(cmd.splitlines()) check_equal(ramdisk, ramdisk_out, 'Ramdisk not loaded') # Configuration with some Loadables - with cons.log.section('Kernel + FDT + Ramdisk load + Loadables'): + with ubman.log.section('Kernel + FDT + Ramdisk load + Loadables'): params['loadables_config'] = 'loadables = "kernel-2", "ramdisk-2";' params['loadables1_load'] = ('load = <%#x>;' % params['loadables1_addr']) params['loadables2_load'] = ('load = <%#x>;' % params['loadables2_addr']) - fit = fit_util.make_fit(cons, mkimage, base_its, params) - cons.restart_uboot() - output = cons.run_command_list(cmd.splitlines()) + fit = fit_util.make_fit(ubman, mkimage, base_its, params) + ubman.restart_uboot() + output = ubman.run_command_list(cmd.splitlines()) check_equal(loadables1, loadables1_out, 'Loadables1 (kernel) not loaded') check_equal(loadables2, loadables2_out, 'Loadables2 (ramdisk) not loaded') # Kernel, FDT and Ramdisk all compressed - with cons.log.section('(Kernel + FDT + Ramdisk) compressed'): + with ubman.log.section('(Kernel + FDT + Ramdisk) compressed'): params['compression'] = 'gzip' params['kernel'] = make_compressed(kernel) params['fdt'] = make_compressed(fdt) params['ramdisk'] = make_compressed(ramdisk) - fit = fit_util.make_fit(cons, mkimage, base_its, params) - cons.restart_uboot() - output = cons.run_command_list(cmd.splitlines()) + fit = fit_util.make_fit(ubman, mkimage, base_its, params) + ubman.restart_uboot() + output = ubman.run_command_list(cmd.splitlines()) check_equal(kernel, kernel_out, 'Kernel not loaded') check_equal(control_dtb, fdt_out, 'FDT not loaded') check_not_equal(ramdisk, ramdisk_out, 'Ramdisk got decompressed?') check_equal(ramdisk + '.gz', ramdisk_out, 'Ramdist not loaded') - cons = ubman # We need to use our own device tree file. Remember to restore it # afterwards. - old_dtb = cons.config.dtb + old_dtb = ubman.config.dtb try: - mkimage = cons.config.build_dir + '/tools/mkimage' + mkimage = ubman.config.build_dir + '/tools/mkimage' run_fit_test(mkimage) finally: # Go back to the original U-Boot with the correct dtb. - cons.config.dtb = old_dtb - cons.restart_uboot() + ubman.config.dtb = old_dtb + ubman.restart_uboot() diff --git a/test/py/tests/test_fit_auto_signed.py b/test/py/tests/test_fit_auto_signed.py index b5f872f3d0f..cdfd341c6f5 100644 --- a/test/py/tests/test_fit_auto_signed.py +++ b/test/py/tests/test_fit_auto_signed.py @@ -26,22 +26,22 @@ from Cryptodome.Signature import pkcs1_15 class SignedFitHelper(object): """Helper to manipulate a FIT with signed/hashed images/configs.""" - def __init__(self, cons, file_name): + def __init__(self, ubman, file_name): self.fit = file_name - self.cons = cons + self.ubman = ubman self.images_nodes = set() self.confgs_nodes = set() def __fdt_list(self, path): - return utils.run_and_log(self.cons, + return utils.run_and_log(self.ubman, f'fdtget -l {self.fit} {path}') def __fdt_get_string(self, node, prop): - return utils.run_and_log(self.cons, + return utils.run_and_log(self.ubman, f'fdtget -ts {self.fit} {node} {prop}') def __fdt_get_binary(self, node, prop): - numbers = utils.run_and_log(self.cons, + numbers = utils.run_and_log(self.ubman, f'fdtget -tbi {self.fit} {node} {prop}') bignum = bytearray() @@ -133,9 +133,8 @@ def test_fit_auto_signed(ubman): The test does not run the sandbox. It only checks the host tool mkimage. """ - cons = ubman - mkimage = cons.config.build_dir + '/tools/mkimage' - tempdir = os.path.join(cons.config.result_dir, 'auto_fit') + mkimage = ubman.config.build_dir + '/tools/mkimage' + tempdir = os.path.join(ubman.config.result_dir, 'auto_fit') os.makedirs(tempdir, exist_ok=True) kernel_file = f'{tempdir}/vmlinuz' dt1_file = f'{tempdir}/dt-1.dtb' @@ -166,29 +165,29 @@ def test_fit_auto_signed(ubman): s_args = " -k" + tempdir + " -g" + key_name + " -o" + sign_algo # 1 - Create auto FIT with images crc32 checksum, and verify it - utils.run_and_log(cons, mkimage + ' -fauto' + b_args + " " + fit_file) + utils.run_and_log(ubman, mkimage + ' -fauto' + b_args + " " + fit_file) - fit = SignedFitHelper(cons, fit_file) + fit = SignedFitHelper(ubman, fit_file) if fit.build_nodes_sets() == 0: raise ValueError('FIT-1 has no "/image" nor "/configuration" nodes') fit.check_fit_crc32_images() # 2 - Create auto FIT with signed images, and verify it - utils.run_and_log(cons, mkimage + ' -fauto' + b_args + s_args + " " + + utils.run_and_log(ubman, mkimage + ' -fauto' + b_args + s_args + " " + fit_file) - fit = SignedFitHelper(cons, fit_file) + fit = SignedFitHelper(ubman, fit_file) if fit.build_nodes_sets() == 0: raise ValueError('FIT-2 has no "/image" nor "/configuration" nodes') fit.check_fit_signed_images(key_name, sign_algo, verifier) # 3 - Create auto FIT with signed configs and hashed images, and verify it - utils.run_and_log(cons, mkimage + ' -fauto-conf' + b_args + s_args + " " + + utils.run_and_log(ubman, mkimage + ' -fauto-conf' + b_args + s_args + " " + fit_file) - fit = SignedFitHelper(cons, fit_file) + fit = SignedFitHelper(ubman, fit_file) if fit.build_nodes_sets() == 0: raise ValueError('FIT-3 has no "/image" nor "/configuration" nodes') diff --git a/test/py/tests/test_fit_ecdsa.py b/test/py/tests/test_fit_ecdsa.py index 63f2f6a44e6..3e816d68eb6 100644 --- a/test/py/tests/test_fit_ecdsa.py +++ b/test/py/tests/test_fit_ecdsa.py @@ -19,21 +19,21 @@ from Cryptodome.Signature import DSS class SignableFitImage(object): """ Helper to manipulate a FIT image on disk """ - def __init__(self, cons, file_name): + def __init__(self, ubman, file_name): self.fit = file_name - self.cons = cons + self.ubman = ubman self.signable_nodes = set() def __fdt_list(self, path): - return utils.run_and_log(self.cons, f'fdtget -l {self.fit} {path}') + return utils.run_and_log(self.ubman, f'fdtget -l {self.fit} {path}') def __fdt_set(self, node, **prop_value): for prop, value in prop_value.items(): - utils.run_and_log(self.cons, + utils.run_and_log(self.ubman, f'fdtput -ts {self.fit} {node} {prop} {value}') def __fdt_get_binary(self, node, prop): - numbers = utils.run_and_log(self.cons, + numbers = utils.run_and_log(self.ubman, f'fdtget -tbi {self.fit} {node} {prop}') bignum = bytearray() @@ -55,7 +55,7 @@ class SignableFitImage(object): self.__fdt_set(f'{image}/signature', algo='sha256,ecdsa256') def sign(self, mkimage, key_file): - utils.run_and_log(self.cons, [mkimage, '-F', self.fit, f'-G{key_file}']) + utils.run_and_log(self.ubman, [mkimage, '-F', self.fit, f'-G{key_file}']) def check_signatures(self, key): for image in self.signable_nodes: @@ -78,16 +78,15 @@ def test_fit_ecdsa(ubman): def assemble_fit_image(dest_fit, its, destdir): dtc_args = f'-I dts -O dtb -i {destdir}' - utils.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) + utils.run_and_log(ubman, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) def dtc(dts): dtb = dts.replace('.dts', '.dtb') - utils.run_and_log(cons, f'dtc {datadir}/{dts} -O dtb -o {tempdir}/{dtb}') + utils.run_and_log(ubman, f'dtc {datadir}/{dts} -O dtb -o {tempdir}/{dtb}') - cons = ubman - mkimage = cons.config.build_dir + '/tools/mkimage' - datadir = cons.config.source_dir + '/test/py/tests/vboot/' - tempdir = os.path.join(cons.config.result_dir, 'ecdsa') + mkimage = ubman.config.build_dir + '/tools/mkimage' + datadir = ubman.config.source_dir + '/test/py/tests/vboot/' + tempdir = os.path.join(ubman.config.result_dir, 'ecdsa') os.makedirs(tempdir, exist_ok=True) key_file = f'{tempdir}/ecdsa-test-key.pem' fit_file = f'{tempdir}/test.fit' @@ -105,7 +104,7 @@ def test_fit_ecdsa(ubman): assemble_fit_image(fit_file, f'{datadir}/sign-images-sha256.its', tempdir) - fit = SignableFitImage(cons, fit_file) + fit = SignableFitImage(ubman, fit_file) nodes = fit.find_signable_image_nodes() if len(nodes) == 0: raise ValueError('FIT image has no "/image" nodes with "signature"') diff --git a/test/py/tests/test_fit_hashes.py b/test/py/tests/test_fit_hashes.py index bcde045d6c8..07bf0fd5211 100644 --- a/test/py/tests/test_fit_hashes.py +++ b/test/py/tests/test_fit_hashes.py @@ -26,20 +26,20 @@ kernel_hashes = { class ReadonlyFitImage(object): """ Helper to manipulate a FIT image on disk """ - def __init__(self, cons, file_name): + def __init__(self, ubman, file_name): self.fit = file_name - self.cons = cons + self.ubman = ubman self.hashable_nodes = set() def __fdt_list(self, path): - return utils.run_and_log(self.cons, f'fdtget -l {self.fit} {path}') + return utils.run_and_log(self.ubman, f'fdtget -l {self.fit} {path}') def __fdt_get(self, node, prop): - val = utils.run_and_log(self.cons, f'fdtget {self.fit} {node} {prop}') + val = utils.run_and_log(self.ubman, f'fdtget {self.fit} {node} {prop}') return val.rstrip('\n') def __fdt_get_sexadecimal(self, node, prop): - numbers = utils.run_and_log(self.cons, + numbers = utils.run_and_log(self.ubman, f'fdtget -tbx {self.fit} {node} {prop}') sexadecimal = '' @@ -86,17 +86,16 @@ def test_mkimage_hashes(ubman): def assemble_fit_image(dest_fit, its, destdir): dtc_args = f'-I dts -O dtb -i {destdir}' - utils.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) + utils.run_and_log(ubman, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) def dtc(dts): dtb = dts.replace('.dts', '.dtb') - utils.run_and_log(cons, + utils.run_and_log(ubman, f'dtc {datadir}/{dts} -O dtb -o {tempdir}/{dtb}') - cons = ubman - mkimage = cons.config.build_dir + '/tools/mkimage' - datadir = cons.config.source_dir + '/test/py/tests/vboot/' - tempdir = os.path.join(cons.config.result_dir, 'hashes') + mkimage = ubman.config.build_dir + '/tools/mkimage' + datadir = ubman.config.source_dir + '/test/py/tests/vboot/' + tempdir = os.path.join(ubman.config.result_dir, 'hashes') os.makedirs(tempdir, exist_ok=True) fit_file = f'{tempdir}/test.fit' @@ -108,7 +107,7 @@ def test_mkimage_hashes(ubman): assemble_fit_image(fit_file, f'{datadir}/hash-images.its', tempdir) - fit = ReadonlyFitImage(cons, fit_file) + fit = ReadonlyFitImage(ubman, fit_file) nodes = fit.find_hashable_image_nodes() if len(nodes) == 0: raise ValueError('FIT image has no "/image" nodes with "hash-..."') diff --git a/test/py/tests/test_handoff.py b/test/py/tests/test_handoff.py index c0cfa3b3398..becd7d75cf7 100644 --- a/test/py/tests/test_handoff.py +++ b/test/py/tests/test_handoff.py @@ -10,6 +10,5 @@ TEST_HANDOFF_MAGIC = 0x14f93c7b @pytest.mark.buildconfigspec('spl') def test_handoff(ubman): """Test that of-platdata can be generated and used in sandbox""" - cons = ubman - response = cons.run_command('sb handoff') + response = ubman.run_command('sb handoff') assert ('SPL handoff magic %x' % TEST_HANDOFF_MAGIC) in response diff --git a/test/py/tests/test_help.py b/test/py/tests/test_help.py index 72f7282478c..12cb36b7b98 100644 --- a/test/py/tests/test_help.py +++ b/test/py/tests/test_help.py @@ -16,10 +16,9 @@ def test_help(ubman): @pytest.mark.boardspec('sandbox') def test_help_no_devicetree(ubman): try: - cons = ubman - cons.restart_uboot_with_flags([], use_dtb=False) - cons.run_command('help') - output = cons.get_spawn_output().replace('\r', '') + ubman.restart_uboot_with_flags([], use_dtb=False) + ubman.run_command('help') + output = ubman.get_spawn_output().replace('\r', '') assert 'print command description/usage' in output finally: # Restart afterward to get the normal device tree back @@ -28,10 +27,9 @@ def test_help_no_devicetree(ubman): @pytest.mark.boardspec('sandbox_vpl') def test_vpl_help(ubman): try: - cons = ubman - cons.restart_uboot() - cons.run_command('help') - output = cons.get_spawn_output().replace('\r', '') + ubman.restart_uboot() + ubman.run_command('help') + output = ubman.get_spawn_output().replace('\r', '') assert 'print command description/usage' in output finally: # Restart afterward to get the normal device tree back diff --git a/test/py/tests/test_kconfig.py b/test/py/tests/test_kconfig.py index a3796ea7e47..0c261d47975 100644 --- a/test/py/tests/test_kconfig.py +++ b/test/py/tests/test_kconfig.py @@ -13,11 +13,10 @@ TMPDIR = '/tmp/test_kconfig' @pytest.mark.boardspec('sandbox') def test_kconfig(ubman): """Test build failures when IF_ENABLED_INT() option is not enabled""" - cons = ubman # This detects build errors in test/lib/kconfig.c out = utils.run_and_log( - cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox', + ubman, ['./tools/buildman/buildman', '-m', '--board', 'sandbox', '-a', 'TEST_KCONFIG', '-o', TMPDIR], ignore_errors=True) assert 'invalid_use_of_IF_ENABLED_INT' in out assert 'invalid_use_of_CONFIG_IF_ENABLED_INT' in out @@ -26,11 +25,10 @@ def test_kconfig(ubman): @pytest.mark.boardspec('sandbox_spl') def test_kconfig_spl(ubman): """Test build failures when IF_ENABLED_INT() option is not enabled""" - cons = ubman # This detects build errors in test/lib/kconfig_spl.c out = utils.run_and_log( - cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox_spl', + ubman, ['./tools/buildman/buildman', '-m', '--board', 'sandbox_spl', '-a', 'TEST_KCONFIG', '-o', TMPDIR], ignore_errors=True) assert 'invalid_use_of_IF_ENABLED_INT' in out diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py index 292f5b31675..4558b037e2a 100644 --- a/test/py/tests/test_log.py +++ b/test/py/tests/test_log.py @@ -20,18 +20,17 @@ def test_log_format(ubman): fmt: Format to use for 'log format' expected_output: Expected output from the 'log rec' command """ - output = cons.run_command('log format %s' % fmt) + output = ubman.run_command('log format %s' % fmt) assert output == '' - output = cons.run_command('log rec arch notice file.c 123 func msg') + output = ubman.run_command('log rec arch notice file.c 123 func msg') assert output == expected_output - cons = ubman - with cons.log.section('format'): + with ubman.log.section('format'): pad = int(ubman.config.buildconfig.get('config_logf_func_pad')) padding = ' ' * (pad - len('func')) run_with_format('all', f'NOTICE.arch,file.c:123-{padding}func() msg') - output = cons.run_command('log format') + output = ubman.run_command('log format') assert output == 'Log format: clFLfm' run_with_format('fm', f'{padding}func() msg') @@ -45,7 +44,6 @@ def test_log_format(ubman): def test_log_dropped(ubman): """Test dropped 'log' message when debug_uart is activated""" - cons = ubman - cons.restart_uboot() - output = cons.get_spawn_output().replace('\r', '') + ubman.restart_uboot() + output = ubman.get_spawn_output().replace('\r', '') assert (not 'debug: main' in output) diff --git a/test/py/tests/test_mmc.py b/test/py/tests/test_mmc.py index 4916dcd8529..e751a3bd36a 100644 --- a/test/py/tests/test_mmc.py +++ b/test/py/tests/test_mmc.py @@ -32,19 +32,19 @@ devices = {} mmc_modes_name = [] mmc_modes = [] -def setup_mmc_modes(cons): +def setup_mmc_modes(ubman): global mmc_modes, mmc_modes_name - f = cons.config.env.get('env__mmc_device', None) + f = ubman.config.env.get('env__mmc_device', None) if f: mmc_modes_name = f.get('mmc_modes', None) # Set mmc mode to default mode (legacy), if speed mode config isn't enabled - if cons.config.buildconfig.get('config_mmc_speed_mode_set', 'n') != 'y': + if ubman.config.buildconfig.get('config_mmc_speed_mode_set', 'n') != 'y': mmc_modes = [0] return if mmc_modes_name: - mmc_help = cons.run_command('mmc -help') + mmc_help = ubman.run_command('mmc -help') m = re.search(r"\[MMC_LEGACY(.*\n.+])", mmc_help) modes = [ x.strip() diff --git a/test/py/tests/test_of_migrate.py b/test/py/tests/test_of_migrate.py index e866eebbfd4..ab89332331e 100644 --- a/test/py/tests/test_of_migrate.py +++ b/test/py/tests/test_of_migrate.py @@ -14,11 +14,11 @@ TMPDIR1 = '/tmp/test_no_migrate' TMPDIR2 = '/tmp/test_no_migrate_spl' TMPDIR3 = '/tmp/test_migrate' -def build_for_migrate(cons, replace_pair, board, tmpdir, disable_migrate=True): +def build_for_migrate(ubman, replace_pair, board, tmpdir, disable_migrate=True): """Build an updated U-Boot with a slightly modified device tree Args: - cons (ConsoleBase): U-Boot console + ubman (ConsoleBase): U-Boot console replace_pair (tuple): String to find String to replace it with @@ -26,14 +26,14 @@ def build_for_migrate(cons, replace_pair, board, tmpdir, disable_migrate=True): tmpdir (str): Temporary directory to use disable_migrate (bool): True to disable CONFIG_OF_TAG_MIGRATE in build """ - srcdir = cons.config.source_dir - build_dir = cons.config.build_dir + srcdir = ubman.config.source_dir + build_dir = ubman.config.build_dir # Get the source for the existing dts dt_dir = os.path.join(build_dir, 'arch', 'sandbox', 'dts') orig_fname = os.path.join(dt_dir, 'sandbox.dtb') out_dts = os.path.join(dt_dir, 'sandbox_out.dts') - utils.run_and_log(cons, ['dtc', orig_fname, '-I', 'dtb', '-O', 'dts', + utils.run_and_log(ubman, ['dtc', orig_fname, '-I', 'dtb', '-O', 'dts', '-o', out_dts]) # Update it to use an old tag @@ -45,7 +45,7 @@ def build_for_migrate(cons, replace_pair, board, tmpdir, disable_migrate=True): with open(dts_fname, 'w') as outf: print(data, file=outf) dtb_fname = os.path.join(dt_dir, 'sandbox_oldtag.dtb') - utils.run_and_log(cons, ['dtc', dts_fname, '-o', dtb_fname]) + utils.run_and_log(ubman, ['dtc', dts_fname, '-o', dtb_fname]) migrate = ['-a', '~CONFIG_OF_TAG_MIGRATE'] if disable_migrate else [] @@ -55,7 +55,7 @@ def build_for_migrate(cons, replace_pair, board, tmpdir, disable_migrate=True): env['DEVICE_TREE'] = 'sandbox_new' env['NO_LTO'] = '1' # Speed up build out = utils.run_and_log( - cons, ['./tools/buildman/buildman', '-m', '--board', board, + ubman, ['./tools/buildman/buildman', '-m', '--board', board, *migrate, '-w', '-o', tmpdir], ignore_errors=True, env=env) return out @@ -63,15 +63,14 @@ def build_for_migrate(cons, replace_pair, board, tmpdir, disable_migrate=True): @pytest.mark.boardspec('sandbox') def test_of_no_migrate(ubman): """Test sandbox with old boot phase tags like u-boot,dm-pre-proper""" - cons = ubman - build_for_migrate(cons, ['bootph-some-ram', 'u-boot,dm-pre-proper'], + build_for_migrate(ubman, ['bootph-some-ram', 'u-boot,dm-pre-proper'], 'sandbox', TMPDIR1) # It should fail to run, since the lcd device will not be bound before # relocation. so won't get its frame-buffer memory out = utils.run_and_log( - cons, [os.path.join(TMPDIR1, 'u-boot'), '-D', '-c', 'help'], + ubman, [os.path.join(TMPDIR1, 'u-boot'), '-D', '-c', 'help'], ignore_errors=True) assert "Video device 'lcd' cannot allocate frame buffer memory" in out @@ -82,9 +81,8 @@ def test_of_no_migrate(ubman): @pytest.mark.boardspec('!sandbox_tpl') def test_of_no_migrate_spl(ubman): """Test sandbox with old boot phase tags like u-boot,dm-spl""" - cons = ubman - out = build_for_migrate(cons, ['bootph-pre-ram', 'u-boot,dm-spl'], + out = build_for_migrate(ubman, ['bootph-pre-ram', 'u-boot,dm-spl'], 'sandbox_spl', TMPDIR2) # It should fail to build, since the SPL DT will not include 'spl-test' @@ -96,13 +94,12 @@ def test_of_no_migrate_spl(ubman): @pytest.mark.boardspec('sandbox') def test_of_migrate(ubman): """Test sandbox shows a message when tags were migrated""" - cons = ubman - build_for_migrate(cons, ['bootph-some-ram', 'u-boot,dm-pre-proper'], + build_for_migrate(ubman, ['bootph-some-ram', 'u-boot,dm-pre-proper'], 'sandbox', TMPDIR3, disable_migrate=False) # It should show a migration message out = utils.run_and_log( - cons, [os.path.join(TMPDIR3, 'u-boot'), '-D', '-c', 'help'], + ubman, [os.path.join(TMPDIR3, 'u-boot'), '-D', '-c', 'help'], ignore_errors=True) assert "Warning: Device tree includes old 'u-boot,dm-' tags" in out diff --git a/test/py/tests/test_ofplatdata.py b/test/py/tests/test_ofplatdata.py index b4d2db03deb..d31fa55f7c7 100644 --- a/test/py/tests/test_ofplatdata.py +++ b/test/py/tests/test_ofplatdata.py @@ -8,10 +8,9 @@ import utils @pytest.mark.buildconfigspec('spl_of_platdata') def test_spl_devicetree(ubman): """Test content of spl device-tree""" - cons = ubman - dtb = cons.config.build_dir + '/spl/u-boot-spl.dtb' - fdtgrep = cons.config.build_dir + '/tools/fdtgrep' - output = utils.run_and_log(cons, [fdtgrep, '-l', dtb]) + dtb = ubman.config.build_dir + '/spl/u-boot-spl.dtb' + fdtgrep = ubman.config.build_dir + '/tools/fdtgrep' + output = utils.run_and_log(ubman, [fdtgrep, '-l', dtb]) assert "bootph-all" not in output assert "bootph-some-ram" not in output diff --git a/test/py/tests/test_sandbox_opts.py b/test/py/tests/test_sandbox_opts.py index f50302cbe6b..48f5b313870 100644 --- a/test/py/tests/test_sandbox_opts.py +++ b/test/py/tests/test_sandbox_opts.py @@ -13,18 +13,16 @@ TMPDIR = '/tmp/test_cmdline' @pytest.mark.boardspec('sandbox') def test_sandbox_cmdline(ubman): """Test building sandbox without CONFIG_CMDLINE""" - cons = ubman utils.run_and_log( - cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox', + ubman, ['./tools/buildman/buildman', '-m', '--board', 'sandbox', '-a', '~CMDLINE', '-o', TMPDIR]) @pytest.mark.slow @pytest.mark.boardspec('sandbox') def test_sandbox_lto(ubman): """Test building sandbox without CONFIG_LTO""" - cons = ubman utils.run_and_log( - cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox', + ubman, ['./tools/buildman/buildman', '-m', '--board', 'sandbox', '-a', '~LTO', '-o', TMPDIR]) diff --git a/test/py/tests/test_source.py b/test/py/tests/test_source.py index f0437aa15ca..970d8c79869 100644 --- a/test/py/tests/test_source.py +++ b/test/py/tests/test_source.py @@ -11,27 +11,26 @@ import utils @pytest.mark.buildconfigspec('fit') def test_source(ubman): # Compile our test script image - cons = ubman - mkimage = os.path.join(cons.config.build_dir, 'tools/mkimage') - its = os.path.join(cons.config.source_dir, 'test/py/tests/source.its') - fit = os.path.join(cons.config.build_dir, 'source.itb') - utils.run_and_log(cons, (mkimage, '-f', its, fit)) - cons.run_command(f'host load hostfs - $loadaddr {fit}') + mkimage = os.path.join(ubman.config.build_dir, 'tools/mkimage') + its = os.path.join(ubman.config.source_dir, 'test/py/tests/source.its') + fit = os.path.join(ubman.config.build_dir, 'source.itb') + utils.run_and_log(ubman, (mkimage, '-f', its, fit)) + ubman.run_command(f'host load hostfs - $loadaddr {fit}') - assert '2' in cons.run_command('source') - assert '1' in cons.run_command('source :') - assert '1' in cons.run_command('source :script-1') - assert '2' in cons.run_command('source :script-2') - assert 'Fail' in cons.run_command('source :not-a-script || echo Fail') - assert '2' in cons.run_command('source \\#') - assert '1' in cons.run_command('source \\#conf-1') - assert '2' in cons.run_command('source \\#conf-2') + assert '2' in ubman.run_command('source') + assert '1' in ubman.run_command('source :') + assert '1' in ubman.run_command('source :script-1') + assert '2' in ubman.run_command('source :script-2') + assert 'Fail' in ubman.run_command('source :not-a-script || echo Fail') + assert '2' in ubman.run_command('source \\#') + assert '1' in ubman.run_command('source \\#conf-1') + assert '2' in ubman.run_command('source \\#conf-2') - cons.run_command('fdt addr $loadaddr') - cons.run_command('fdt rm /configurations default') - assert '1' in cons.run_command('source') - assert 'Fail' in cons.run_command('source \\# || echo Fail') + ubman.run_command('fdt addr $loadaddr') + ubman.run_command('fdt rm /configurations default') + assert '1' in ubman.run_command('source') + assert 'Fail' in ubman.run_command('source \\# || echo Fail') - cons.run_command('fdt rm /images default') - assert 'Fail' in cons.run_command('source || echo Fail') - assert 'Fail' in cons.run_command('source \\# || echo Fail') + ubman.run_command('fdt rm /images default') + assert 'Fail' in ubman.run_command('source || echo Fail') + assert 'Fail' in ubman.run_command('source \\# || echo Fail') diff --git a/test/py/tests/test_spl.py b/test/py/tests/test_spl.py index 6b226c256b7..48407399039 100644 --- a/test/py/tests/test_spl.py +++ b/test/py/tests/test_spl.py @@ -33,9 +33,8 @@ def test_spl(ubman, ut_spl_subtest): ut_subtest (str): SPL test to be executed (e.g. 'dm platdata_phandle') """ try: - cons = ubman - cons.restart_uboot_with_flags(['-u', '-k', ut_spl_subtest.split()[1]]) - output = cons.get_spawn_output().replace('\r', '') + ubman.restart_uboot_with_flags(['-u', '-k', ut_spl_subtest.split()[1]]) + output = ubman.get_spawn_output().replace('\r', '') assert 'failures: 0' in output finally: # Restart afterward in case a non-SPL test is run next. This should not diff --git a/test/py/tests/test_suite.py b/test/py/tests/test_suite.py index c7f4dedba51..7fe9a90dfd3 100644 --- a/test/py/tests/test_suite.py +++ b/test/py/tests/test_suite.py @@ -18,11 +18,11 @@ EXPECTED_SUITES = [ DEBUG_ME = False -def collect_info(cons, output): +def collect_info(ubman, output): """Process the output from 'ut all' Args: - cons: U-Boot console object + ubman: U-Boot console object output: Output from running 'ut all' Returns: @@ -45,15 +45,15 @@ def collect_info(cons, output): for line in output.splitlines(): line = line.rstrip() if DEBUG_ME: - cons.log.info(f'line: {line}') + ubman.log.info(f'line: {line}') m = re.search('----Running ([^ ]*) tests----', line) if m: if DEBUG_ME and cur_suite and cur_suite != 'info': - cons.log.info(f'suite: {cur_suite} expected {exp_test_count[cur_suite]} found {test_count}') + ubman.log.info(f'suite: {cur_suite} expected {exp_test_count[cur_suite]} found {test_count}') cur_suite = m.group(1) if DEBUG_ME: - cons.log.info(f'cur_suite: {cur_suite}') + ubman.log.info(f'cur_suite: {cur_suite}') suites.add(cur_suite) test_count = 0 @@ -65,7 +65,7 @@ def collect_info(cons, output): test_name = m.group(1) msg = m.group(3) if DEBUG_ME: - cons.log.info(f"test_name {test_name} msg '{msg}'") + ubman.log.info(f"test_name {test_name} msg '{msg}'") full_name = f'{cur_suite}.{test_name}' if msg == ' (flat tree)' and full_name not in tests: tests.add(full_name) @@ -74,10 +74,10 @@ def collect_info(cons, output): tests.add(full_name) test_count += 1 if DEBUG_ME: - cons.log.info(f'test_count {test_count}') + ubman.log.info(f'test_count {test_count}') if DEBUG_ME: - cons.log.info(f'suite: {cur_suite} expected {exp_test_count[cur_suite]} found {test_count}') - cons.log.info(f"Tests: {' '.join(sorted(list(tests)))}") + ubman.log.info(f'suite: {cur_suite} expected {exp_test_count[cur_suite]} found {test_count}') + ubman.log.info(f"Tests: {' '.join(sorted(list(tests)))}") # Figure out what is missing, or extra missing = set() @@ -91,11 +91,11 @@ def collect_info(cons, output): return suites, tests, exp_test_count, missing, extra -def process_ut_info(cons, output): +def process_ut_info(ubman, output): """Process the output of the 'ut info' command Args: - cons: U-Boot console object + ubman: U-Boot console object output: Output from running 'ut all' Returns: @@ -113,7 +113,7 @@ def process_ut_info(cons, output): for line in output.splitlines(): line = line.rstrip() if DEBUG_ME: - cons.log.info(f'line: {line}') + ubman.log.info(f'line: {line}') m = re.match(r'Test suites: (.*)', line) if m: suite_count = int(m.group(1)) @@ -142,45 +142,44 @@ def xtest_suite(ubman, u_boot_config): - The expected set of suites is run (the list is hard-coded in this test) """ - cons = ubman buildconfig = u_boot_config.buildconfig - with cons.log.section('Run all unit tests'): + with ubman.log.section('Run all unit tests'): # ut hush hush_test_simple_dollar prints "Unknown command" on purpose. with ubman.disable_check('unknown_command'): - output = cons.run_command('ut all') + output = ubman.run_command('ut all') # Process the output from the run - with cons.log.section('Check output'): - suites, all_tests, exp_test_count, missing, extra = collect_info(cons, + with ubman.log.section('Check output'): + suites, all_tests, exp_test_count, missing, extra = collect_info(ubman, output) - cons.log.info(f'missing {missing}') - cons.log.info(f'extra {extra}') + ubman.log.info(f'missing {missing}') + ubman.log.info(f'extra {extra}') # Make sure we got a test count for each suite assert not (suites - exp_test_count.keys()) # Deal with missing suites - with cons.log.section('Check missing suites'): + with ubman.log.section('Check missing suites'): if 'config_cmd_seama' not in buildconfig: - cons.log.info("CMD_SEAMA not enabled: Ignoring suite 'seama'") + ubman.log.info("CMD_SEAMA not enabled: Ignoring suite 'seama'") missing.discard('seama') # Run 'ut info' and compare with the log results - with cons.log.section('Check suite test-counts'): - output = cons.run_command('ut -s info') + with ubman.log.section('Check suite test-counts'): + output = ubman.run_command('ut -s info') - suite_count, total_test_count, test_count = process_ut_info(cons, + suite_count, total_test_count, test_count = process_ut_info(ubman, output) if missing or extra: - cons.log.info(f"suites: {' '.join(sorted(list(suites)))}") - cons.log.error(f'missing: {sorted(list(missing))}') - cons.log.error(f'extra: {sorted(list(extra))}') + ubman.log.info(f"suites: {' '.join(sorted(list(suites)))}") + ubman.log.error(f'missing: {sorted(list(missing))}') + ubman.log.error(f'extra: {sorted(list(extra))}') assert not missing, f'Missing suites {missing}' assert not extra, f'Extra suites {extra}' - cons.log.info(str(exp_test_count)) + ubman.log.info(str(exp_test_count)) for suite in EXPECTED_SUITES: assert test_count[suite] in ['?', str(exp_test_count[suite])], \ f'suite {suite} expected {exp_test_count[suite]}' @@ -189,18 +188,18 @@ def xtest_suite(ubman, u_boot_config): assert total_test_count == len(all_tests) # Run three suites - with cons.log.section('Check multiple suites'): - output = cons.run_command('ut bloblist,setexpr,mem') + with ubman.log.section('Check multiple suites'): + output = ubman.run_command('ut bloblist,setexpr,mem') assert 'Suites run: 3' in output # Run a particular test - with cons.log.section('Check single test'): - output = cons.run_command('ut bloblist reloc') + with ubman.log.section('Check single test'): + output = ubman.run_command('ut bloblist reloc') assert 'Test: reloc: bloblist.c' in output # Run tests multiple times - with cons.log.section('Check multiple runs'): - output = cons.run_command('ut -r2 bloblist') + with ubman.log.section('Check multiple runs'): + output = ubman.run_command('ut -r2 bloblist') lines = output.splitlines() run = len([line for line in lines if 'Test:' in line]) count = re.search(r'Tests run: (\d*)', lines[-1]).group(1) diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py index ade102a387e..064651c3e23 100644 --- a/test/py/tests/test_tpm2.py +++ b/test/py/tests/test_tpm2.py @@ -50,9 +50,9 @@ def force_init(ubman, force=False): ubman.run_command('tpm2 clear TPM2_RH_PLATFORM') ubman.run_command('echo --- end of init ---') -def is_sandbox(cons): +def is_sandbox(ubman): # Array slice removes leading/trailing quotes. - sys_arch = cons.config.buildconfig.get('config_sys_arch', '"sandbox"')[1:-1] + sys_arch = ubman.config.buildconfig.get('config_sys_arch', '"sandbox"')[1:-1] return sys_arch == 'sandbox' @pytest.mark.buildconfigspec('cmd_tpm_v2') diff --git a/test/py/tests/test_trace.py b/test/py/tests/test_trace.py index 72f65f2b347..6ac1b225465 100644 --- a/test/py/tests/test_trace.py +++ b/test/py/tests/test_trace.py @@ -15,19 +15,19 @@ TMPDIR = '/tmp/test_trace' RE_LINE = re.compile(r'.*0\.\.\.\.\.? \s*([0-9.]*): func.*[|](\s*)(\S.*)?([{};])$') -def collect_trace(cons): +def collect_trace(ubman): """Build U-Boot and run it to collect a trace Args: - cons (ConsoleBase): U-Boot console + ubman (ConsoleBase): U-Boot console Returns: tuple: str: Filename of the output trace file int: Microseconds taken for initf_dm according to bootstage """ - cons.run_command('trace pause') - out = cons.run_command('trace stats') + ubman.run_command('trace pause') + out = ubman.run_command('trace stats') # The output is something like this: # 251,003 function sites @@ -48,10 +48,10 @@ def collect_trace(cons): assert int(vals['untracked function calls']) == 0 assert int(vals['maximum observed call depth']) > 30 assert (vals['call depth limit'] == - cons.config.buildconfig.get('config_trace_call_depth_limit')) + ubman.config.buildconfig.get('config_trace_call_depth_limit')) assert int(vals['calls not traced due to depth']) > 100000 - out = cons.run_command('bootstage report') + out = ubman.run_command('bootstage report') # Accumulated time: # 19,104 dm_r # 23,078 of_live @@ -62,26 +62,26 @@ def collect_trace(cons): # Read out the trace data addr = 0x02000000 size = 0x02000000 - out = cons.run_command(f'trace calls {addr:x} {size:x}') + out = ubman.run_command(f'trace calls {addr:x} {size:x}') print(out) fname = os.path.join(TMPDIR, 'trace') - out = cons.run_command( + out = ubman.run_command( 'host save hostfs - %x %s ${profoffset}' % (addr, fname)) return fname, int(dm_f_time[0]) -def wipe_and_collect_trace(cons): +def wipe_and_collect_trace(ubman): """Pause and wipe traces, return the number of calls (should be zero) Args: - cons (ConsoleBase): U-Boot console + ubman (ConsoleBase): U-Boot console Returns: int: the number of traced function calls reported by 'trace stats' """ - cons.run_command('trace pause') - cons.run_command('trace wipe') - out = cons.run_command('trace stats') + ubman.run_command('trace pause') + ubman.run_command('trace wipe') + out = ubman.run_command('trace stats') # The output is something like this: # 117,221 function sites @@ -96,22 +96,22 @@ def wipe_and_collect_trace(cons): return int(vals['traced function calls']) -def check_function(cons, fname, proftool, map_fname, trace_dat): +def check_function(ubman, fname, proftool, map_fname, trace_dat): """Check that the 'function' output works Args: - cons (ConsoleBase): U-Boot console + ubman (ConsoleBase): U-Boot console fname (str): Filename of trace file proftool (str): Filename of proftool map_fname (str): Filename of System.map trace_dat (str): Filename of output file """ out = utils.run_and_log( - cons, [proftool, '-t', fname, '-o', trace_dat, '-m', map_fname, + ubman, [proftool, '-t', fname, '-o', trace_dat, '-m', map_fname, 'dump-ftrace']) # Check that trace-cmd can read it - out = utils.run_and_log(cons, ['trace-cmd', 'dump', trace_dat]) + out = utils.run_and_log(ubman, ['trace-cmd', 'dump', trace_dat]) # Tracing meta data in file /tmp/test_trace/trace.dat: # [Initial format] @@ -140,7 +140,7 @@ def check_function(cons, fname, proftool, map_fname, trace_dat): # Check that the trace has something useful cmd = f"trace-cmd report -l {trace_dat} |grep -E '(initf_|initr_)'" - out = utils.run_and_log(cons, ['sh', '-c', cmd]) + out = utils.run_and_log(ubman, ['sh', '-c', cmd]) # Format: # u-boot-1 0..... 60.805596: function: initf_malloc @@ -167,11 +167,11 @@ def check_function(cons, fname, proftool, map_fname, trace_dat): assert max_delta < 5 -def check_funcgraph(cons, fname, proftool, map_fname, trace_dat): +def check_funcgraph(ubman, fname, proftool, map_fname, trace_dat): """Check that the 'funcgraph' output works Args: - cons (ConsoleBase): U-Boot console + ubman (ConsoleBase): U-Boot console fname (str): Filename of trace file proftool (str): Filename of proftool map_fname (str): Filename of System.map @@ -183,12 +183,12 @@ def check_funcgraph(cons, fname, proftool, map_fname, trace_dat): # Generate the funcgraph format out = utils.run_and_log( - cons, [proftool, '-t', fname, '-o', trace_dat, '-m', map_fname, + ubman, [proftool, '-t', fname, '-o', trace_dat, '-m', map_fname, 'dump-ftrace', '-f', 'funcgraph']) # Check that the trace has what we expect cmd = f'trace-cmd report -l {trace_dat} |head -n 70' - out = utils.run_and_log(cons, ['sh', '-c', cmd]) + out = utils.run_and_log(ubman, ['sh', '-c', cmd]) # First look for this: # u-boot-1 0..... 282.101360: funcgraph_entry: 0.004 us | initf_malloc(); @@ -230,7 +230,7 @@ def check_funcgraph(cons, fname, proftool, map_fname, trace_dat): # Now look for initf_dm() and dm_timer_init() so we can check the bootstage # time cmd = f"trace-cmd report -l {trace_dat} |grep -E '(initf_dm|dm_timer_init)'" - out = utils.run_and_log(cons, ['sh', '-c', cmd]) + out = utils.run_and_log(ubman, ['sh', '-c', cmd]) start_timestamp = None end_timestamp = None @@ -249,14 +249,14 @@ def check_funcgraph(cons, fname, proftool, map_fname, trace_dat): return int((float(end_timestamp) - float(start_timestamp)) * 1000000) -def check_flamegraph(cons, fname, proftool, map_fname, trace_fg): +def check_flamegraph(ubman, fname, proftool, map_fname, trace_fg): """Check that the 'flamegraph' output works This spot checks a few call counts and estimates the time taken by the initf_dm() function Args: - cons (ConsoleBase): U-Boot console + ubman (ConsoleBase): U-Boot console fname (str): Filename of trace file proftool (str): Filename of proftool map_fname (str): Filename of System.map @@ -268,7 +268,7 @@ def check_flamegraph(cons, fname, proftool, map_fname, trace_fg): # Generate the flamegraph format out = utils.run_and_log( - cons, [proftool, '-t', fname, '-o', trace_fg, '-m', map_fname, + ubman, [proftool, '-t', fname, '-o', trace_fg, '-m', map_fname, 'dump-flamegraph']) # We expect dm_timer_init() to be called twice: once before relocation and @@ -285,7 +285,7 @@ def check_flamegraph(cons, fname, proftool, map_fname, trace_fg): # Generate the timing graph utils.run_and_log( - cons, [proftool, '-t', fname, '-o', trace_fg, '-m', map_fname, + ubman, [proftool, '-t', fname, '-o', trace_fg, '-m', map_fname, 'dump-flamegraph', '-f', 'timing']) # Add up all the time spend in initf_dm() and its children @@ -305,26 +305,25 @@ check_flamegraph @pytest.mark.buildconfigspec('trace') def test_trace(ubman): """Test we can build sandbox with trace, collect and process a trace""" - cons = ubman if not os.path.exists(TMPDIR): os.mkdir(TMPDIR) - proftool = os.path.join(cons.config.build_dir, 'tools', 'proftool') - map_fname = os.path.join(cons.config.build_dir, 'System.map') + proftool = os.path.join(ubman.config.build_dir, 'tools', 'proftool') + map_fname = os.path.join(ubman.config.build_dir, 'System.map') trace_dat = os.path.join(TMPDIR, 'trace.dat') trace_fg = os.path.join(TMPDIR, 'trace.fg') - fname, dm_f_time = collect_trace(cons) + fname, dm_f_time = collect_trace(ubman) - check_function(cons, fname, proftool, map_fname, trace_dat) - trace_time = check_funcgraph(cons, fname, proftool, map_fname, trace_dat) + check_function(ubman, fname, proftool, map_fname, trace_dat) + trace_time = check_funcgraph(ubman, fname, proftool, map_fname, trace_dat) # Check that bootstage and funcgraph agree to within 10 microseconds diff = abs(trace_time - dm_f_time) print(f'trace_time {trace_time}, dm_f_time {dm_f_time}') assert diff / dm_f_time < 0.01 - fg_time = check_flamegraph(cons, fname, proftool, map_fname, trace_fg) + fg_time = check_flamegraph(ubman, fname, proftool, map_fname, trace_fg) # Check that bootstage and flamegraph agree to within 30% # This allows for CI being slow to run @@ -332,5 +331,5 @@ def test_trace(ubman): assert diff / dm_f_time < 0.3 # Check that the trace buffer can be wiped - numcalls = wipe_and_collect_trace(cons) + numcalls = wipe_and_collect_trace(ubman) assert numcalls == 0 diff --git a/test/py/tests/test_upl.py b/test/py/tests/test_upl.py index c8eeaa024e5..c79c32adf0b 100644 --- a/test/py/tests/test_upl.py +++ b/test/py/tests/test_upl.py @@ -19,20 +19,19 @@ def test_upl_handoff(ubman): The entire FIT is loaded into memory in SPL (in upl_load_from_image()) so that it can be inspected in upl_test_info_norun """ - cons = ubman - ram = os.path.join(cons.config.build_dir, 'ram.bin') - fdt = os.path.join(cons.config.build_dir, 'u-boot.dtb') + ram = os.path.join(ubman.config.build_dir, 'ram.bin') + fdt = os.path.join(ubman.config.build_dir, 'u-boot.dtb') # Remove any existing RAM file, so we don't have old data present if os.path.exists(ram): os.remove(ram) flags = ['-m', ram, '-d', fdt, '--upl'] - cons.restart_uboot_with_flags(flags, use_dtb=False) + ubman.restart_uboot_with_flags(flags, use_dtb=False) # Make sure that Universal Payload is detected in U-Boot proper - output = cons.run_command('upl info') + output = ubman.run_command('upl info') assert 'UPL state: active' == output # Check the FIT offsets look correct - output = cons.run_command('ut upl -f upl_test_info_norun') + output = ubman.run_command('ut upl -f upl_test_info_norun') assert 'failures: 0' in output diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index d7cf95d461b..ea0c43cd4fc 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -27,12 +27,12 @@ def mkdir_cond(dirname): if not os.path.exists(dirname): os.mkdir(dirname) -def setup_image(cons, devnum, part_type, img_size=20, second_part=False, +def setup_image(ubman, devnum, part_type, img_size=20, second_part=False, basename='mmc'): """Create a disk image with a single partition Args: - cons (ConsoleBase): Console to use + ubman (ConsoleBase): Console to use devnum (int): Device number to use, e.g. 1 part_type (int): Partition type, e.g. 0xc for FAT32 img_size (int): Image size in MiB @@ -44,26 +44,26 @@ def setup_image(cons, devnum, part_type, img_size=20, second_part=False, str: Filename of MMC image str: Directory name of scratch directory """ - fname = os.path.join(cons.config.source_dir, f'{basename}{devnum}.img') - mnt = os.path.join(cons.config.persistent_data_dir, 'scratch') + fname = os.path.join(ubman.config.source_dir, f'{basename}{devnum}.img') + mnt = os.path.join(ubman.config.persistent_data_dir, 'scratch') mkdir_cond(mnt) spec = f'type={part_type:x}, size={img_size - 2}M, start=1M, bootable' if second_part: spec += '\ntype=c' - utils.run_and_log(cons, f'qemu-img create {fname} 20M') - utils.run_and_log(cons, f'sfdisk {fname}', + utils.run_and_log(ubman, f'qemu-img create {fname} 20M') + utils.run_and_log(ubman, f'sfdisk {fname}', stdin=spec.encode('utf-8')) return fname, mnt -def setup_bootmenu_image(cons): +def setup_bootmenu_image(ubman): """Create a 20MB disk image with a single ext4 partition This is modelled on Armbian 22.08 Jammy """ mmc_dev = 4 - fname, mnt = setup_image(cons, mmc_dev, 0x83) + fname, mnt = setup_image(ubman, mmc_dev, 0x83) script = '''# DO NOT EDIT THIS FILE # @@ -146,16 +146,16 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} with open(cmd_fname, 'w', encoding='ascii') as outf: print(script, file=outf) - infname = os.path.join(cons.config.source_dir, + infname = os.path.join(ubman.config.source_dir, 'test/py/tests/bootstd/armbian.bmp.xz') bmp_file = os.path.join(bootdir, 'boot.bmp') utils.run_and_log( - cons, + ubman, ['sh', '-c', f'xz -dc {infname} >{bmp_file}']) - mkimage = cons.config.build_dir + '/tools/mkimage' + mkimage = ubman.config.build_dir + '/tools/mkimage' utils.run_and_log( - cons, f'{mkimage} -C none -A arm -T script -d {cmd_fname} {scr_fname}') + ubman, f'{mkimage} -C none -A arm -T script -d {cmd_fname} {scr_fname}') kernel = 'vmlinuz-5.15.63-rockchip64' target = os.path.join(bootdir, kernel) @@ -166,20 +166,20 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} if os.path.exists(symlink): os.remove(symlink) utils.run_and_log( - cons, f'echo here {kernel} {symlink}') + ubman, f'echo here {kernel} {symlink}') os.symlink(kernel, symlink) fsfile = 'ext18M.img' - utils.run_and_log(cons, f'fallocate -l 18M {fsfile}') - utils.run_and_log(cons, f'mkfs.ext4 {fsfile} -d {mnt}') - utils.run_and_log(cons, f'dd if={fsfile} of={fname} bs=1M seek=1') - utils.run_and_log(cons, f'rm -rf {mnt}') - utils.run_and_log(cons, f'rm -f {fsfile}') + utils.run_and_log(ubman, f'fallocate -l 18M {fsfile}') + utils.run_and_log(ubman, f'mkfs.ext4 {fsfile} -d {mnt}') + utils.run_and_log(ubman, f'dd if={fsfile} of={fname} bs=1M seek=1') + utils.run_and_log(ubman, f'rm -rf {mnt}') + utils.run_and_log(ubman, f'rm -f {fsfile}') -def setup_bootflow_image(cons): +def setup_bootflow_image(ubman): """Create a 20MB disk image with a single FAT partition""" mmc_dev = 1 - fname, mnt = setup_image(cons, mmc_dev, 0xc, second_part=True) + fname, mnt = setup_image(ubman, mmc_dev, 0xc, second_part=True) vmlinux = 'vmlinuz-5.3.7-301.fc31.armv7hl' initrd = 'initramfs-5.3.7-301.fc31.armv7hl.img' @@ -204,12 +204,12 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) with open(conf, 'w', encoding='ascii') as fd: print(script, file=fd) - inf = os.path.join(cons.config.persistent_data_dir, 'inf') + inf = os.path.join(ubman.config.persistent_data_dir, 'inf') with open(inf, 'wb') as fd: fd.write(gzip.compress(b'vmlinux')) - mkimage = cons.config.build_dir + '/tools/mkimage' + mkimage = ubman.config.build_dir + '/tools/mkimage' utils.run_and_log( - cons, f'{mkimage} -f auto -d {inf} {os.path.join(mnt, vmlinux)}') + ubman, f'{mkimage} -f auto -d {inf} {os.path.join(mnt, vmlinux)}') with open(os.path.join(mnt, initrd), 'w', encoding='ascii') as fd: print('initrd', file=fd) @@ -218,27 +218,27 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) dtb_file = os.path.join(mnt, f'{dtbdir}/sandbox.dtb') utils.run_and_log( - cons, f'dtc -o {dtb_file}', stdin=b'/dts-v1/; / {};') + ubman, f'dtc -o {dtb_file}', stdin=b'/dts-v1/; / {};') fsfile = 'vfat18M.img' - utils.run_and_log(cons, f'fallocate -l 18M {fsfile}') - utils.run_and_log(cons, f'mkfs.vfat {fsfile}') - utils.run_and_log(cons, ['sh', '-c', f'mcopy -i {fsfile} {mnt}/* ::/']) - utils.run_and_log(cons, f'dd if={fsfile} of={fname} bs=1M seek=1') - utils.run_and_log(cons, f'rm -rf {mnt}') - utils.run_and_log(cons, f'rm -f {fsfile}') - -def setup_cros_image(cons): + utils.run_and_log(ubman, f'fallocate -l 18M {fsfile}') + utils.run_and_log(ubman, f'mkfs.vfat {fsfile}') + utils.run_and_log(ubman, ['sh', '-c', f'mcopy -i {fsfile} {mnt}/* ::/']) + utils.run_and_log(ubman, f'dd if={fsfile} of={fname} bs=1M seek=1') + utils.run_and_log(ubman, f'rm -rf {mnt}') + utils.run_and_log(ubman, f'rm -f {fsfile}') + +def setup_cros_image(ubman): """Create a 20MB disk image with ChromiumOS partitions""" Partition = collections.namedtuple('part', 'start,size,name') parts = {} disk_data = None - def pack_kernel(cons, arch, kern, dummy): + def pack_kernel(ubman, arch, kern, dummy): """Pack a kernel containing some fake data Args: - cons (ConsoleBase): Console to use + ubman (ConsoleBase): Console to use arch (str): Architecture to use ('x86' or 'arm') kern (str): Filename containing kernel dummy (str): Dummy filename to use for config and bootloader @@ -246,10 +246,10 @@ def setup_cros_image(cons): Return: bytes: Packed-kernel data """ - kern_part = os.path.join(cons.config.result_dir, + kern_part = os.path.join(ubman.config.result_dir, f'kern-part-{arch}.bin') utils.run_and_log( - cons, + ubman, f'futility vbutil_kernel --pack {kern_part} ' '--keyblock doc/chromium/files/devkeys/kernel.keyblock ' '--signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk ' @@ -275,9 +275,9 @@ def setup_cros_image(cons): disk_data = disk_data[:start] + data + disk_data[start + len(data):] mmc_dev = 5 - fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') - utils.run_and_log(cons, f'qemu-img create {fname} 20M') - utils.run_and_log(cons, f'cgpt create {fname}') + fname = os.path.join(ubman.config.source_dir, f'mmc{mmc_dev}.img') + utils.run_and_log(ubman, f'qemu-img create {fname} 20M') + utils.run_and_log(ubman, f'cgpt create {fname}') uuid_state = 'ebd0a0a2-b9e5-4433-87c0-68b6b72699c7' uuid_kern = 'fe3a2a5d-4f32-41a7-b725-accc3285a309' @@ -317,12 +317,12 @@ def setup_cros_image(cons): else: size = int(size_str) utils.run_and_log( - cons, + ubman, f"cgpt add -i {part['num']} -b {ptr} -s {size} -t {part['type']} {fname}") ptr += size - utils.run_and_log(cons, f'cgpt boot -p {fname}') - out = utils.run_and_log(cons, f'cgpt show -q {fname}') + utils.run_and_log(ubman, f'cgpt boot -p {fname}') + out = utils.run_and_log(ubman, f'cgpt show -q {fname}') # We expect something like this: # 8239 2048 1 Basic data @@ -344,14 +344,14 @@ def setup_cros_image(cons): parts[int(num)] = Partition(int(start), int(size), name) # Set up the kernel command-line - dummy = os.path.join(cons.config.result_dir, 'dummy.txt') + dummy = os.path.join(ubman.config.result_dir, 'dummy.txt') with open(dummy, 'wb') as outf: outf.write(b'BOOT_IMAGE=/vmlinuz-5.15.0-121-generic root=/dev/nvme0n1p1 ro quiet splash vt.handoff=7') # For now we just use dummy kernels. This limits testing to just detecting # a signed kernel. We could add support for the x86 data structures so that # testing could cover getting the cmdline, setup.bin and other pieces. - kern = os.path.join(cons.config.result_dir, 'kern.bin') + kern = os.path.join(ubman.config.result_dir, 'kern.bin') with open(kern, 'wb') as outf: outf.write(b'kernel\n') @@ -359,15 +359,15 @@ def setup_cros_image(cons): disk_data = inf.read() # put x86 kernel in partition 2 and arm one in partition 4 - set_part_data(2, pack_kernel(cons, 'x86', kern, dummy)) - set_part_data(4, pack_kernel(cons, 'arm', kern, dummy)) + set_part_data(2, pack_kernel(ubman, 'x86', kern, dummy)) + set_part_data(4, pack_kernel(ubman, 'arm', kern, dummy)) with open(fname, 'wb') as outf: outf.write(disk_data) return fname -def setup_android_image(cons): +def setup_android_image(ubman): """Create a 20MB disk image with Android partitions""" Partition = collections.namedtuple('part', 'start,size,name') parts = {} @@ -388,9 +388,9 @@ def setup_android_image(cons): disk_data = disk_data[:start] + data + disk_data[start + len(data):] mmc_dev = 7 - fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') - utils.run_and_log(cons, f'qemu-img create {fname} 20M') - utils.run_and_log(cons, f'cgpt create {fname}') + fname = os.path.join(ubman.config.source_dir, f'mmc{mmc_dev}.img') + utils.run_and_log(ubman, f'qemu-img create {fname} 20M') + utils.run_and_log(ubman, f'cgpt create {fname}') ptr = 40 @@ -413,12 +413,12 @@ def setup_android_image(cons): else: size = int(size_str) utils.run_and_log( - cons, + ubman, f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}") ptr += size - utils.run_and_log(cons, f'cgpt boot -p {fname}') - out = utils.run_and_log(cons, f'cgpt show -q {fname}') + utils.run_and_log(ubman, f'cgpt boot -p {fname}') + out = utils.run_and_log(ubman, f'cgpt show -q {fname}') # Create a dict (indexed by partition number) containing the above info for line in out.splitlines(): @@ -428,13 +428,13 @@ def setup_android_image(cons): with open(fname, 'rb') as inf: disk_data = inf.read() - test_abootimg.AbootimgTestDiskImage(cons, 'bootv4.img', test_abootimg.boot_img_hex) - boot_img = os.path.join(cons.config.result_dir, 'bootv4.img') + test_abootimg.AbootimgTestDiskImage(ubman, 'bootv4.img', test_abootimg.boot_img_hex) + boot_img = os.path.join(ubman.config.result_dir, 'bootv4.img') with open(boot_img, 'rb') as inf: set_part_data(2, inf.read()) - test_abootimg.AbootimgTestDiskImage(cons, 'vendor_boot.img', test_abootimg.vboot_img_hex) - vendor_boot_img = os.path.join(cons.config.result_dir, 'vendor_boot.img') + test_abootimg.AbootimgTestDiskImage(ubman, 'vendor_boot.img', test_abootimg.vboot_img_hex) + vendor_boot_img = os.path.join(ubman.config.result_dir, 'vendor_boot.img') with open(vendor_boot_img, 'rb') as inf: set_part_data(4, inf.read()) @@ -444,9 +444,9 @@ def setup_android_image(cons): print(f'wrote to {fname}') mmc_dev = 8 - fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') - utils.run_and_log(cons, f'qemu-img create {fname} 20M') - utils.run_and_log(cons, f'cgpt create {fname}') + fname = os.path.join(ubman.config.source_dir, f'mmc{mmc_dev}.img') + utils.run_and_log(ubman, f'qemu-img create {fname} 20M') + utils.run_and_log(ubman, f'cgpt create {fname}') ptr = 40 @@ -467,12 +467,12 @@ def setup_android_image(cons): else: size = int(size_str) utils.run_and_log( - cons, + ubman, f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}") ptr += size - utils.run_and_log(cons, f'cgpt boot -p {fname}') - out = utils.run_and_log(cons, f'cgpt show -q {fname}') + utils.run_and_log(ubman, f'cgpt boot -p {fname}') + out = utils.run_and_log(ubman, f'cgpt show -q {fname}') # Create a dict (indexed by partition number) containing the above info for line in out.splitlines(): @@ -482,8 +482,8 @@ def setup_android_image(cons): with open(fname, 'rb') as inf: disk_data = inf.read() - test_abootimg.AbootimgTestDiskImage(cons, 'boot.img', test_abootimg.img_hex) - boot_img = os.path.join(cons.config.result_dir, 'boot.img') + test_abootimg.AbootimgTestDiskImage(ubman, 'boot.img', test_abootimg.img_hex) + boot_img = os.path.join(ubman.config.result_dir, 'boot.img') with open(boot_img, 'rb') as inf: set_part_data(2, inf.read()) @@ -494,16 +494,16 @@ def setup_android_image(cons): return fname -def setup_cedit_file(cons): +def setup_cedit_file(ubman): """Set up a .dtb file for use with testing expo and configuration editor""" - infname = os.path.join(cons.config.source_dir, + infname = os.path.join(ubman.config.source_dir, 'test/boot/files/expo_layout.dts') - inhname = os.path.join(cons.config.source_dir, + inhname = os.path.join(ubman.config.source_dir, 'test/boot/files/expo_ids.h') - expo_tool = os.path.join(cons.config.source_dir, 'tools/expo.py') + expo_tool = os.path.join(ubman.config.source_dir, 'tools/expo.py') outfname = 'cedit.dtb' utils.run_and_log( - cons, f'{expo_tool} -e {inhname} -l {infname} -o {outfname}') + ubman, f'{expo_tool} -e {inhname} -l {infname} -o {outfname}') @pytest.mark.buildconfigspec('ut_dm') def test_ut_dm_init(ubman): @@ -541,30 +541,30 @@ def test_ut_dm_init(ubman): fh.write(data) -def setup_efi_image(cons): +def setup_efi_image(ubman): """Create a 20MB disk image with an EFI app on it""" devnum = 1 basename = 'flash' - fname, mnt = setup_image(cons, devnum, 0xc, second_part=True, + fname, mnt = setup_image(ubman, devnum, 0xc, second_part=True, basename=basename) efi_dir = os.path.join(mnt, 'EFI') mkdir_cond(efi_dir) bootdir = os.path.join(efi_dir, 'BOOT') mkdir_cond(bootdir) - efi_src = os.path.join(cons.config.build_dir, + efi_src = os.path.join(ubman.config.build_dir, 'lib/efi_loader/testapp.efi') efi_dst = os.path.join(bootdir, 'BOOTSBOX.EFI') with open(efi_src, 'rb') as inf: with open(efi_dst, 'wb') as outf: outf.write(inf.read()) fsfile = 'vfat18M.img' - utils.run_and_log(cons, f'fallocate -l 18M {fsfile}') - utils.run_and_log(cons, f'mkfs.vfat {fsfile}') - utils.run_and_log(cons, ['sh', '-c', f'mcopy -vs -i {fsfile} {mnt}/* ::/']) - utils.run_and_log(cons, f'dd if={fsfile} of={fname} bs=1M seek=1') - utils.run_and_log(cons, f'rm -rf {mnt}') - utils.run_and_log(cons, f'rm -f {fsfile}') + utils.run_and_log(ubman, f'fallocate -l 18M {fsfile}') + utils.run_and_log(ubman, f'mkfs.vfat {fsfile}') + utils.run_and_log(ubman, ['sh', '-c', f'mcopy -vs -i {fsfile} {mnt}/* ::/']) + utils.run_and_log(ubman, f'dd if={fsfile} of={fname} bs=1M seek=1') + utils.run_and_log(ubman, f'rm -rf {mnt}') + utils.run_and_log(ubman, f'rm -f {fsfile}') @pytest.mark.buildconfigspec('cmd_bootflow') @pytest.mark.buildconfigspec('sandbox') diff --git a/test/py/tests/test_vbe.py b/test/py/tests/test_vbe.py index 876d22fa809..a1f32f375b6 100644 --- a/test/py/tests/test_vbe.py +++ b/test/py/tests/test_vbe.py @@ -91,10 +91,9 @@ ut bootstd -f vbe_test_fixup_norun @pytest.mark.boardspec('sandbox_flattree') @pytest.mark.requiredtool('dtc') def test_vbe(ubman): - cons = ubman - kernel = fit_util.make_kernel(cons, 'vbe-kernel.bin', 'kernel') - fdt = fit_util.make_dtb(cons, base_fdt, 'vbe-fdt') - fdt_out = fit_util.make_fname(cons, 'fdt-out.dtb') + kernel = fit_util.make_kernel(ubman, 'vbe-kernel.bin', 'kernel') + fdt = fit_util.make_dtb(ubman, base_fdt, 'vbe-fdt') + fdt_out = fit_util.make_fname(ubman, 'fdt-out.dtb') params = { 'fit_addr' : 0x1000, @@ -108,13 +107,13 @@ def test_vbe(ubman): 'compression' : 'none', } - mkimage = cons.config.build_dir + '/tools/mkimage' - fit = fit_util.make_fit(cons, mkimage, base_its, params, 'test-vbe.fit', + mkimage = ubman.config.build_dir + '/tools/mkimage' + fit = fit_util.make_fit(ubman, mkimage, base_its, params, 'test-vbe.fit', base_fdt) params['fit'] = fit cmd = base_script % params - with cons.log.section('Kernel load'): - output = cons.run_command_list(cmd.splitlines()) + with ubman.log.section('Kernel load'): + output = ubman.run_command_list(cmd.splitlines()) assert 'failures: 0' in output[-1] diff --git a/test/py/tests/test_vbe_vpl.py b/test/py/tests/test_vbe_vpl.py index 317a324281e..f011b034f63 100644 --- a/test/py/tests/test_vbe_vpl.py +++ b/test/py/tests/test_vbe_vpl.py @@ -11,30 +11,29 @@ import utils @pytest.mark.boardspec('sandbox_vpl') @pytest.mark.requiredtool('dtc') def test_vbe_vpl(ubman): - cons = ubman - #cmd = [cons.config.build_dir + fname, '-v'] - ram = os.path.join(cons.config.build_dir, 'ram.bin') - fdt = os.path.join(cons.config.build_dir, 'arch/sandbox/dts/test.dtb') - image_fname = os.path.join(cons.config.build_dir, 'image.bin') + #cmd = [ubman.config.build_dir + fname, '-v'] + ram = os.path.join(ubman.config.build_dir, 'ram.bin') + fdt = os.path.join(ubman.config.build_dir, 'arch/sandbox/dts/test.dtb') + image_fname = os.path.join(ubman.config.build_dir, 'image.bin') # Enable firmware1 and the mmc that it uses. These are needed for the full # VBE flow. utils.run_and_log( - cons, f'fdtput -t s {fdt} /bootstd/firmware0 status disabled') + ubman, f'fdtput -t s {fdt} /bootstd/firmware0 status disabled') utils.run_and_log( - cons, f'fdtput -t s {fdt} /bootstd/firmware1 status okay') + ubman, f'fdtput -t s {fdt} /bootstd/firmware1 status okay') utils.run_and_log( - cons, f'fdtput -t s {fdt} /mmc3 status okay') + ubman, f'fdtput -t s {fdt} /mmc3 status okay') utils.run_and_log( - cons, f'fdtput -t s {fdt} /mmc3 filename {image_fname}') + ubman, f'fdtput -t s {fdt} /mmc3 filename {image_fname}') # Remove any existing RAM file, so we don't have old data present if os.path.exists(ram): os.remove(ram) flags = ['-p', image_fname, '-w', '-s', 'state.dtb'] - cons.restart_uboot_with_flags(flags) + ubman.restart_uboot_with_flags(flags) # Make sure that VBE was used in both VPL (to load SPL) and SPL (to load # U-Boot - output = cons.run_command('vbe state') + output = ubman.run_command('vbe state') assert output == 'Phases: VPL SPL' diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py index 2b29871b7d4..7a7f9c379de 100644 --- a/test/py/tests/test_vboot.py +++ b/test/py/tests/test_vboot.py @@ -47,7 +47,7 @@ import vboot_forge import vboot_evil # Common helper functions -def dtc(dts, cons, dtc_args, datadir, tmpdir, dtb): +def dtc(dts, ubman, dtc_args, datadir, tmpdir, dtb): """Run the device tree compiler to compile a .dts file The output file will be the same as the input file but with a .dtb @@ -55,30 +55,30 @@ def dtc(dts, cons, dtc_args, datadir, tmpdir, dtb): Args: dts: Device tree file to compile. - cons: U-Boot console. + ubman: U-Boot console. dtc_args: DTC arguments. datadir: Path to data directory. tmpdir: Path to temp directory. dtb: Resulting DTB file. """ dtb = dts.replace('.dts', '.dtb') - utils.run_and_log(cons, 'dtc %s %s%s -O dtb ' + utils.run_and_log(ubman, 'dtc %s %s%s -O dtb ' '-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb)) -def make_fit(its, cons, mkimage, dtc_args, datadir, fit): +def make_fit(its, ubman, mkimage, dtc_args, datadir, fit): """Make a new FIT from the .its source file. This runs 'mkimage -f' to create a new FIT. Args: its: Filename containing .its source. - cons: U-Boot console. + ubman: U-Boot console. mkimage: Path to mkimage utility. dtc_args: DTC arguments. datadir: Path to data directory. fit: Resulting FIT file. """ - utils.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', + utils.run_and_log(ubman, [mkimage, '-D', dtc_args, '-f', '%s%s' % (datadir, its), fit]) # Only run the full suite on a few combinations, since it doesn't add any more @@ -134,7 +134,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, options: Options provided to the compiler. """ dtb = dts.replace('.dts', '.dtb') - utils.run_and_log(cons, 'dtc %s %s%s -O dtb -o %s%s %s' % + utils.run_and_log(ubman, 'dtc %s %s%s -O dtb -o %s%s %s' % (dtc_args, datadir, dts, tmpdir, dtb, options)) def run_binman(dtb): @@ -145,7 +145,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, """ pythonpath = os.environ.get('PYTHONPATH', '') os.environ['PYTHONPATH'] = pythonpath + ':' + '%s/../scripts/dtc/pylibfdt' % tmpdir - utils.run_and_log(cons, [binman, 'build', '-d', "%s/%s" % (tmpdir,dtb), + utils.run_and_log(ubman, [binman, 'build', '-d', "%s/%s" % (tmpdir,dtb), '-a', "pre-load-key-path=%s" % tmpdir, '-O', tmpdir, '-I', tmpdir]) os.environ['PYTHONPATH'] = pythonpath @@ -167,9 +167,9 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, """ if not fit: fit = '%stest.fit' % tmpdir - cons.restart_uboot() - with cons.log.section('Verified boot %s %s' % (sha_algo, test_type)): - output = cons.run_command_list( + ubman.restart_uboot() + with ubman.log.section('Verified boot %s %s' % (sha_algo, test_type)): + output = ubman.run_command_list( ['host load hostfs - 100 %s' % fit, 'fdt addr 100', 'bootm 100']) @@ -194,8 +194,8 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, args = [mkimage, '-F', '-k', tmpdir, '-K', dtb, '-r', fit] if options: args += options.split(' ') - cons.log.action('%s: Sign images' % sha_algo) - utils.run_and_log(cons, args) + ubman.log.action('%s: Sign images' % sha_algo) + utils.run_and_log(ubman, args) def sign_fit_dtb(sha_algo, options, dtb): """Sign the FIT @@ -211,8 +211,8 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, args = [mkimage, '-F', '-k', tmpdir, '-K', dtb, '-r', fit] if options: args += options.split(' ') - cons.log.action('%s: Sign images' % sha_algo) - utils.run_and_log(cons, args) + ubman.log.action('%s: Sign images' % sha_algo) + utils.run_and_log(ubman, args) def sign_fit_norequire(sha_algo, options): """Sign the FIT @@ -228,8 +228,8 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, args = [mkimage, '-F', '-k', tmpdir, '-K', dtb, fit] if options: args += options.split(' ') - cons.log.action('%s: Sign images' % sha_algo) - utils.run_and_log(cons, args) + ubman.log.action('%s: Sign images' % sha_algo) + utils.run_and_log(ubman, args) def replace_fit_totalsize(size): """Replace FIT header's totalsize with something greater. @@ -278,13 +278,13 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, else: rsa_keygen_bits = 2048 - utils.run_and_log(cons, 'openssl genpkey -algorithm RSA -out %s%s.key ' + utils.run_and_log(ubman, 'openssl genpkey -algorithm RSA -out %s%s.key ' '-pkeyopt rsa_keygen_bits:%d ' '-pkeyopt rsa_keygen_pubexp:%d' % (tmpdir, name, rsa_keygen_bits, public_exponent)) # Create a certificate containing the public key - utils.run_and_log(cons, 'openssl req -batch -new -x509 -key %s%s.key ' + utils.run_and_log(ubman, 'openssl req -batch -new -x509 -key %s%s.key ' '-out %s%s.crt' % (tmpdir, name, tmpdir, name)) def test_with_algo(sha_algo, padding, sign_options): @@ -303,12 +303,12 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, # Compile our device tree files for kernel and U-Boot. These are # regenerated here since mkimage will modify them (by adding a # public key) below. - dtc('sandbox-kernel.dts', cons, dtc_args, datadir, tmpdir, dtb) - dtc('sandbox-u-boot.dts', cons, dtc_args, datadir, tmpdir, dtb) + dtc('sandbox-kernel.dts', ubman, dtc_args, datadir, tmpdir, dtb) + dtc('sandbox-u-boot.dts', ubman, dtc_args, datadir, tmpdir, dtb) # Build the FIT, but don't sign anything yet - cons.log.action('%s: Test FIT with signed images' % sha_algo) - make_fit('sign-images-%s%s.its' % (sha_algo, padding), cons, mkimage, dtc_args, datadir, fit) + ubman.log.action('%s: Test FIT with signed images' % sha_algo) + make_fit('sign-images-%s%s.its' % (sha_algo, padding), ubman, mkimage, dtc_args, datadir, fit) run_bootm(sha_algo, 'unsigned images', ' - OK' if algo_arg else 'dev-', True) # Sign images with our dev keys @@ -316,19 +316,19 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, run_bootm(sha_algo, 'signed images', 'dev+', True) # Create a fresh .dtb without the public keys - dtc('sandbox-u-boot.dts', cons, dtc_args, datadir, tmpdir, dtb) + dtc('sandbox-u-boot.dts', ubman, dtc_args, datadir, tmpdir, dtb) - cons.log.action('%s: Test FIT with signed configuration' % sha_algo) - make_fit('sign-configs-%s%s.its' % (sha_algo, padding), cons, mkimage, dtc_args, datadir, fit) + ubman.log.action('%s: Test FIT with signed configuration' % sha_algo) + make_fit('sign-configs-%s%s.its' % (sha_algo, padding), ubman, mkimage, dtc_args, datadir, fit) run_bootm(sha_algo, 'unsigned config', '%s+ OK' % ('sha256' if algo_arg else sha_algo), True) # Sign images with our dev keys sign_fit(sha_algo, sign_options) run_bootm(sha_algo, 'signed config', 'dev+', True) - cons.log.action('%s: Check signed config on the host' % sha_algo) + ubman.log.action('%s: Check signed config on the host' % sha_algo) - utils.run_and_log(cons, [fit_check_sign, '-f', fit, '-k', dtb]) + utils.run_and_log(ubman, [fit_check_sign, '-f', fit, '-k', dtb]) if full_test: # Make sure that U-Boot checks that the config is in the list of @@ -341,7 +341,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, with open(ffit, 'w+b') as fd: vboot_forge.write_fdt(root, strblock, fd) utils.run_and_log_expect_exception( - cons, [fit_check_sign, '-f', ffit, '-k', dtb], + ubman, [fit_check_sign, '-f', ffit, '-k', dtb], 1, 'Failed to verify required signature') run_bootm(sha_algo, 'forged config', 'Bad Data Hash', False, ffit) @@ -352,7 +352,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, vboot_evil.add_evil_node(fit, efit, evil_kernel, 'fakeroot') utils.run_and_log_expect_exception( - cons, [fit_check_sign, '-f', efit, '-k', dtb], + ubman, [fit_check_sign, '-f', efit, '-k', dtb], 1, 'Failed to verify required signature') run_bootm(sha_algo, 'evil fakeroot', 'Bad FIT kernel image format', False, efit) @@ -364,41 +364,41 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, msg = 'Signature checking prevents use of unit addresses (@) in nodes' utils.run_and_log_expect_exception( - cons, [fit_check_sign, '-f', efit, '-k', dtb], + ubman, [fit_check_sign, '-f', efit, '-k', dtb], 1, msg) run_bootm(sha_algo, 'evil kernel@', msg, False, efit) # Create a new properly signed fit and replace header bytes - make_fit('sign-configs-%s%s.its' % (sha_algo, padding), cons, mkimage, dtc_args, datadir, fit) + make_fit('sign-configs-%s%s.its' % (sha_algo, padding), ubman, mkimage, dtc_args, datadir, fit) sign_fit(sha_algo, sign_options) bcfg = ubman.config.buildconfig max_size = int(bcfg.get('config_fit_signature_max_size', 0x10000000), 0) existing_size = replace_fit_totalsize(max_size + 1) run_bootm(sha_algo, 'Signed config with bad hash', 'Bad Data Hash', False) - cons.log.action('%s: Check overflowed FIT header totalsize' % sha_algo) + ubman.log.action('%s: Check overflowed FIT header totalsize' % sha_algo) # Replace with existing header bytes replace_fit_totalsize(existing_size) run_bootm(sha_algo, 'signed config', 'dev+', True) - cons.log.action('%s: Check default FIT header totalsize' % sha_algo) + ubman.log.action('%s: Check default FIT header totalsize' % sha_algo) # Increment the first byte of the signature, which should cause failure - sig = utils.run_and_log(cons, 'fdtget -t bx %s %s value' % + sig = utils.run_and_log(ubman, 'fdtget -t bx %s %s value' % (fit, sig_node)) byte_list = sig.split() byte = int(byte_list[0], 16) byte_list[0] = '%x' % (byte + 1) sig = ' '.join(byte_list) - utils.run_and_log(cons, 'fdtput -t bx %s %s value %s' % + utils.run_and_log(ubman, 'fdtput -t bx %s %s value %s' % (fit, sig_node, sig)) run_bootm(sha_algo, 'Signed config with bad hash', 'Bad Data Hash', False) - cons.log.action('%s: Check bad config on the host' % sha_algo) + ubman.log.action('%s: Check bad config on the host' % sha_algo) utils.run_and_log_expect_exception( - cons, [fit_check_sign, '-f', fit, '-k', dtb], + ubman, [fit_check_sign, '-f', fit, '-k', dtb], 1, 'Failed to verify required signature') def test_required_key(sha_algo, padding, sign_options): @@ -416,19 +416,19 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, # Compile our device tree files for kernel and U-Boot. These are # regenerated here since mkimage will modify them (by adding a # public key) below. - dtc('sandbox-kernel.dts', cons, dtc_args, datadir, tmpdir, dtb) - dtc('sandbox-u-boot.dts', cons, dtc_args, datadir, tmpdir, dtb) + dtc('sandbox-kernel.dts', ubman, dtc_args, datadir, tmpdir, dtb) + dtc('sandbox-u-boot.dts', ubman, dtc_args, datadir, tmpdir, dtb) - cons.log.action('%s: Test FIT with configs images' % sha_algo) + ubman.log.action('%s: Test FIT with configs images' % sha_algo) # Build the FIT with prod key (keys required) and sign it. This puts the # signature into sandbox-u-boot.dtb, marked 'required' - make_fit('sign-configs-%s%s-prod.its' % (sha_algo, padding), cons, mkimage, dtc_args, datadir, fit) + make_fit('sign-configs-%s%s-prod.its' % (sha_algo, padding), ubman, mkimage, dtc_args, datadir, fit) sign_fit(sha_algo, sign_options) # Build the FIT with dev key (keys NOT required). This adds the # signature into sandbox-u-boot.dtb, NOT marked 'required'. - make_fit('sign-configs-%s%s.its' % (sha_algo, padding), cons, mkimage, dtc_args, datadir, fit) + make_fit('sign-configs-%s%s.its' % (sha_algo, padding), ubman, mkimage, dtc_args, datadir, fit) sign_fit_norequire(sha_algo, sign_options) # So now sandbox-u-boot.dtb two signatures, for the prod and dev keys. @@ -440,7 +440,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, # Build the FIT with dev key (keys required) and sign it. This puts the # signature into sandbox-u-boot.dtb, marked 'required'. - make_fit('sign-configs-%s%s.its' % (sha_algo, padding), cons, mkimage, dtc_args, datadir, fit) + make_fit('sign-configs-%s%s.its' % (sha_algo, padding), ubman, mkimage, dtc_args, datadir, fit) sign_fit(sha_algo, sign_options) # Set the required-mode policy to "any". @@ -449,7 +449,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, # a dev signature only (sign_fit() overwrites the FIT). # Try to boot the FIT with dev key. This FIT should be accepted by # U-Boot because the dev key is required and policy is "any" required key. - utils.run_and_log(cons, 'fdtput -t s %s /signature required-mode any' % + utils.run_and_log(ubman, 'fdtput -t s %s /signature required-mode any' % dtb) run_bootm(sha_algo, 'multi required key', 'dev+', True) @@ -459,7 +459,7 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, # a dev signature only (sign_fit() overwrites the FIT). # Try to boot the FIT with dev key. This FIT should not be accepted by # U-Boot because the prod key is required and policy is "all" required key - utils.run_and_log(cons, 'fdtput -t s %s /signature required-mode all' % + utils.run_and_log(ubman, 'fdtput -t s %s /signature required-mode all' % dtb) run_bootm(sha_algo, 'multi required key', '', False) @@ -473,22 +473,22 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, """ dtb = '%ssandbox-u-boot-global%s.dtb' % (tmpdir, padding) - cons.config.dtb = dtb + ubman.config.dtb = dtb # Compile our device tree files for kernel and U-Boot. These are # regenerated here since mkimage will modify them (by adding a # public key) below. - dtc('sandbox-kernel.dts', cons, dtc_args, datadir, tmpdir, dtb) + dtc('sandbox-kernel.dts', ubman, dtc_args, datadir, tmpdir, dtb) dtc_options('sandbox-u-boot-global%s.dts' % padding, '-p 1024') # Build the FIT with dev key (keys NOT required). This adds the # signature into sandbox-u-boot.dtb, NOT marked 'required'. - make_fit('simple-images.its', cons, mkimage, dtc_args, datadir, fit) + make_fit('simple-images.its', ubman, mkimage, dtc_args, datadir, fit) sign_fit_dtb(sha_algo, '', dtb) # Build the dtb for binman that define the pre-load header # with the global sigature. - dtc('sandbox-binman%s.dts' % padding, cons, dtc_args, datadir, tmpdir, dtb) + dtc('sandbox-binman%s.dts' % padding, ubman, dtc_args, datadir, tmpdir, dtb) # Run binman to create the final image with the not signed fit # and the pre-load header that contains the global signature. @@ -508,15 +508,14 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, # Check that the boot fails if the global signature is not provided run_bootm(sha_algo, 'global image signature', 'signature is mandatory', False) - cons = ubman - tmpdir = os.path.join(cons.config.result_dir, name) + '/' + tmpdir = os.path.join(ubman.config.result_dir, name) + '/' if not os.path.exists(tmpdir): os.mkdir(tmpdir) - datadir = cons.config.source_dir + '/test/py/tests/vboot/' + datadir = ubman.config.source_dir + '/test/py/tests/vboot/' fit = '%stest.fit' % tmpdir - mkimage = cons.config.build_dir + '/tools/mkimage' - binman = cons.config.source_dir + '/tools/binman/binman' - fit_check_sign = cons.config.build_dir + '/tools/fit_check_sign' + mkimage = ubman.config.build_dir + '/tools/mkimage' + binman = ubman.config.source_dir + '/tools/binman/binman' + fit_check_sign = ubman.config.build_dir + '/tools/fit_check_sign' dtc_args = '-I dts -O dtb -i %s' % tmpdir dtb = '%ssandbox-u-boot.dtb' % tmpdir sig_node = '/configurations/conf-1/signature' @@ -535,9 +534,9 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, # We need to use our own device tree file. Remember to restore it # afterwards. - old_dtb = cons.config.dtb + old_dtb = ubman.config.dtb try: - cons.config.dtb = dtb + ubman.config.dtb = dtb if global_sign: test_global_sign(sha_algo, padding, sign_options) elif required: @@ -546,8 +545,8 @@ def test_vboot(ubman, name, sha_algo, padding, sign_options, required, test_with_algo(sha_algo, padding, sign_options) finally: # Go back to the original U-Boot with the correct dtb. - cons.config.dtb = old_dtb - cons.restart_uboot() + ubman.config.dtb = old_dtb + ubman.restart_uboot() TESTDATA_IN = [ @@ -593,8 +592,8 @@ def test_fdt_add_pubkey(ubman, name, sha_algo, padding, sign_options, algo_arg): args = [mkimage, '-F', '-k', tmpdir, fit] if options: args += options.split(' ') - cons.log.action('%s: Sign images' % sha_algo) - utils.run_and_log(cons, args) + ubman.log.action('%s: Sign images' % sha_algo) + utils.run_and_log(ubman, args) def test_add_pubkey(sha_algo, padding, sign_options): """Test fdt_add_pubkey utility with given hash algorithm and padding. @@ -609,34 +608,33 @@ def test_fdt_add_pubkey(ubman, name, sha_algo, padding, sign_options, algo_arg): """ # Create a fresh .dtb without the public keys - dtc('sandbox-u-boot.dts', cons, dtc_args, datadir, tmpdir, dtb) + dtc('sandbox-u-boot.dts', ubman, dtc_args, datadir, tmpdir, dtb) - cons.log.action('%s: Test fdt_add_pubkey with signed configuration' % sha_algo) + ubman.log.action('%s: Test fdt_add_pubkey with signed configuration' % sha_algo) # Then add the dev key via the fdt_add_pubkey tool - utils.run_and_log(cons, + utils.run_and_log(ubman, [fdt_add_pubkey, '-a', '%s,%s' % ('sha256' if algo_arg else sha_algo, 'rsa3072' if sha_algo == 'sha384' else 'rsa2048'), '-k', tmpdir, '-n', 'dev', '-r', 'conf', dtb]) - make_fit('sign-configs-%s%s.its' % (sha_algo, padding), cons, mkimage, dtc_args, datadir, fit) + make_fit('sign-configs-%s%s.its' % (sha_algo, padding), ubman, mkimage, dtc_args, datadir, fit) # Sign images with our dev keys sign_fit(sha_algo, sign_options) # Check with fit_check_sign that FIT is signed with key - utils.run_and_log(cons, [fit_check_sign, '-f', fit, '-k', dtb]) + utils.run_and_log(ubman, [fit_check_sign, '-f', fit, '-k', dtb]) - cons = ubman - tmpdir = os.path.join(cons.config.result_dir, name) + '/' + tmpdir = os.path.join(ubman.config.result_dir, name) + '/' if not os.path.exists(tmpdir): os.mkdir(tmpdir) - datadir = cons.config.source_dir + '/test/py/tests/vboot/' + datadir = ubman.config.source_dir + '/test/py/tests/vboot/' fit = '%stest.fit' % tmpdir - mkimage = cons.config.build_dir + '/tools/mkimage' - binman = cons.config.source_dir + '/tools/binman/binman' - fit_check_sign = cons.config.build_dir + '/tools/fit_check_sign' - fdt_add_pubkey = cons.config.build_dir + '/tools/fdt_add_pubkey' + mkimage = ubman.config.build_dir + '/tools/mkimage' + binman = ubman.config.source_dir + '/tools/binman/binman' + fit_check_sign = ubman.config.build_dir + '/tools/fit_check_sign' + fdt_add_pubkey = ubman.config.build_dir + '/tools/fdt_add_pubkey' dtc_args = '-I dts -O dtb -i %s' % tmpdir dtb = '%ssandbox-u-boot.dtb' % tmpdir diff --git a/test/py/tests/test_vpl.py b/test/py/tests/test_vpl.py index 735e2c3bbbe..a269c7c262e 100644 --- a/test/py/tests/test_vpl.py +++ b/test/py/tests/test_vpl.py @@ -23,9 +23,8 @@ def test_vpl(ubman, ut_vpl_subtest): ut_subtest (str): VPL test to be executed (e.g. 'dm platdata_phandle') """ try: - cons = ubman - cons.restart_uboot_with_flags(['-u', '-k', ut_vpl_subtest.split()[1]]) - output = cons.get_spawn_output().replace('\r', '') + ubman.restart_uboot_with_flags(['-u', '-k', ut_vpl_subtest.split()[1]]) + output = ubman.get_spawn_output().replace('\r', '') assert 'failures: 0' in output finally: # Restart afterward in case a non-VPL test is run next. This should not -- cgit v1.3.1