On 09/18/2018 07:23 PM, Stephen Warren wrote: > On 09/18/2018 11:21 AM, Heinrich Schuchardt wrote: >> Spawn.exept has a try block without 'except'. >> >> If no output is available an OSError may arise. Catch this exception and >> continue testing. >> >> Signed-off-by: Heinrich Schuchardt <xypron.g...@gmx.de> >> Reviewed-by: Simon Glass <s...@chromium.org> >> --- >> I suggest that Alex takes the patch because we need it when working on >> the >> efi-next branch. >> >> v2 >> replace TAB by spaces >> fix typo in subject > > I'll point out that I still object to this. >
On 09/18/2018 07:06 PM, Stephen Warren wrote: > This doesn't make sense at all. It catches all errors and ignores them. > It'll turn any error condition into a timeout (presumably, the expected > data being waited for will never appear) rather than dealing with it > immediately (due to the thrown exception). Why is this needed? > When the py test is running it is connected via pipes to the U-Boot process. If the U-Boot process ends due to a segmentation fault the pipes are broken. Trying to read from a broken pipe results in an OSError. Before this patch this leads to an uncaught error in the Python script. The output that has occured up to this point is lost and not displayed. All further tests for the configuration are not run. An example can be seen at the end of https://api.travis-ci.org/v3/job/429566431/log.txt . I have copied the relevant part of the output below. Please, observe that the output that has occurred until the segmentation fault is not displayed. Instead we see lines with "INTERNAL ERROR>". The same can be observed when executing make mrproper && make tests Further below I have copied the output with the patch. Here the OSError is caught and the py tests continue as expected. Best regards Heinrich === Output without the patch === test/py/tests/test_efi_selftest.py F INTERNALERROR> Traceback (most recent call last): INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/_pytest/main.py", line 178, in wrap_session INTERNALERROR> session.exitstatus = doit(config, session) or 0 INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/_pytest/main.py", line 215, in _main INTERNALERROR> config.hook.pytest_runtestloop(session=session) INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/hooks.py", line 258, in __call__ INTERNALERROR> return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs) INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/manager.py", line 67, in _hookexec INTERNALERROR> return self._inner_hookexec(hook, methods, kwargs) INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/manager.py", line 61, in <lambda> INTERNALERROR> firstresult=hook.spec_opts.get('firstresult'), INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/callers.py", line 201, in _multicall INTERNALERROR> return outcome.get_result() INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/callers.py", line 77, in get_result INTERNALERROR> _reraise(*ex) # noqa INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/callers.py", line 180, in _multicall INTERNALERROR> res = hook_impl.function(*args) INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/_pytest/main.py", line 236, in pytest_runtestloop INTERNALERROR> item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem) INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/hooks.py", line 258, in __call__ INTERNALERROR> return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs) INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/manager.py", line 67, in _hookexec INTERNALERROR> return self._inner_hookexec(hook, methods, kwargs) INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/manager.py", line 61, in <lambda> INTERNALERROR> firstresult=hook.spec_opts.get('firstresult'), INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/callers.py", line 201, in _multicall INTERNALERROR> return outcome.get_result() INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/callers.py", line 77, in get_result INTERNALERROR> _reraise(*ex) # noqa INTERNALERROR> File "/tmp/venv/local/lib/python2.7/site-packages/pluggy/callers.py", line 180, in _multicall INTERNALERROR> res = hook_impl.function(*args) INTERNALERROR> File "/home/travis/build/agraf/u-boot/test/py/conftest.py", line 577, in pytest_runtest_protocol INTERNALERROR> console.drain_console() INTERNALERROR> File "/home/travis/build/agraf/u-boot/test/py/u_boot_console_base.py", line 306, in drain_console INTERNALERROR> self.p.expect(['This should never match U-Boot output']) INTERNALERROR> File "/home/travis/build/agraf/u-boot/test/py/u_boot_spawn.py", line 174, in expect INTERNALERROR> c = os.read(self.fd, 1024) INTERNALERROR> OSError: [Errno 5] Input/output error === Output with the patch === $ make tests ./test/run +make O=/home/user/workspace/u-boot-build/denx/build-sandbox -s sandbox_defconfig +make O=/home/user/workspace/u-boot-build/denx/build-sandbox -s -j8 =========================================================================== test session starts ============================================================================ platform linux2 -- Python 2.7.15+, pytest-3.6.4, py-1.6.0, pluggy-0.6.0 rootdir: /home/user/workspace/u-boot-build/denx/test/py, inifile: pytest.ini collected 411 items test/py/tests/test_000_version.py . [ 0%] test/py/tests/test_avb.py sssss [ 0%] test/py/tests/test_bind.py .. [ 0%] test/py/tests/test_dfu.py s [ 0%] test/py/tests/test_efi_loader.py .sssss [ 0%] test/py/tests/test_efi_selftest.py FFFFF [ 0%] test/py/tests/test_env.py ............ [ 0%] test/py/tests/test_fit.py F [ 0%] test/py/tests/test_fpga.py sssssssssssssssssssssssssss [ 0%] test/py/tests/test_gpt.py sssssss [ 0%] test/py/tests/test_help.py . [ 0%] test/py/tests/test_hush_if_test.py ....................................................... [ 0%] test/py/tests/test_log.py .. [ 0%] test/py/tests/test_md.py .. [ 0%] test/py/tests/test_mmc_rd.py s [ 0%] test/py/tests/test_net.py .sssss [ 0%] test/py/tests/test_ofplatdata.py s [ 0%] test/py/tests/test_sandbox_exit.py .. [ 0%] test/py/tests/test_sf.py ssss [ 0%] test/py/tests/test_shell_basics.py .... [ 0%] test/py/tests/test_sleep.py . [ 0%] test/py/tests/test_tpm2.py ........... [ 0%] test/py/tests/test_ums.py s [ 0%] test/py/tests/test_unknown_cmd.py . [ 0%] test/py/tests/test_ut.py ........................................................................................................................................................................ [ 0%] test/py/tests/test_vboot.py F[sudo] password for user: [ 0%] test/py/tests/test_fs/test_basic.py sssssssssssssssssssssssssssssssssssssss [ 0%] test/py/tests/test_fs/test_ext.py ssssssssssssssssss [ 0%] test/py/tests/test_fs/test_mkdir.py ssssssssssss [ 0%] test/py/tests/test_fs/test_unlink.py ssssssssssssss ================================================================================= FAILURES ================================================================================= ____________________________________________________________________________ test_efi_selftest _____________________________________________________________________________ u_boot_console = <u_boot_console_sandbox.ConsoleSandbox object at 0x7fb32ef7cfd0> @pytest.mark.buildconfigspec('cmd_bootefi_selftest') def test_efi_selftest(u_boot_console): """ Run bootefi selftest """ u_boot_console.run_command(cmd='setenv efi_selftest') u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False) m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key']) if m != 0: > raise Exception('Failures occurred during the EFI selftest') E Exception: Failures occurred during the EFI selftest test/py/tests/test_efi_selftest.py:19: Exception --------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------- => setenv efi_selftest => => bootefi selftest Scanning disk mmc2.blk... ^[[44;172R______________________________________________________________________ test_efi_selftest_device_tree _______________________________________________________________________ u_boot_console = <u_boot_console_sandbox.ConsoleSandbox object at 0x7fb32ef7cfd0> @pytest.mark.buildconfigspec('cmd_bootefi_selftest') @pytest.mark.buildconfigspec('of_control') def test_efi_selftest_device_tree(u_boot_console): u_boot_console.run_command(cmd='setenv efi_selftest list') > output = u_boot_console.run_command('bootefi selftest') test/py/tests/test_efi_selftest.py:30: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <u_boot_console_sandbox.ConsoleSandbox object at 0x7fb32ef7cfd0>, cmd = '', wait_for_echo = True, send_nl = True, wait_for_prompt = True def run_command(self, cmd, wait_for_echo=True, send_nl=True, wait_for_prompt=True): """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. 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 send_nl: cmd += '\n' while cmd: # Limit max outstanding data, so UART FIFOs don't overflow chunk = cmd[:self.max_fifo_fill] cmd = cmd[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 Exception('Bad pattern found on console: ' + self.bad_pattern_ids[m - 1]) if not wait_for_prompt: return m = self.p.expect([self.prompt_compiled] + self.bad_patterns) if m != 0: self.at_prompt = False raise Exception('Bad pattern found on console: ' + > self.bad_pattern_ids[m - 1]) E TypeError: unsupported operand type(s) for -: 'NoneType' and 'int' test/py/u_boot_console_base.py:207: TypeError -------------------------------------------------------------------------- Captured stdout setup --------------------------------------------------------------------------- /u-boot _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot