@@ -13,6 +13,7 @@ class Emulator(object):
# can take a long time to run the emulator. Use a timeout multiplier
# when running the tests to avoid sporadic failures.
self.timeout_multiplier = timeout_multiplier
+ self.shell_prompt = "#BRTEST# "
# Start Qemu to boot the system
#
@@ -100,6 +101,16 @@ class Emulator(object):
index = self.qemu.expect(["# ", pexpect.TIMEOUT])
if index != 0:
raise SystemError("Cannot login")
+ # We set a special shell prompt for testing. Since the
+ # standard prompt '# ' is quite generic, a normal process
+ # output could contain that string and confuse expect. When
+ # changing the prompt, we also need to slightly obfuscate it
+ # in some way to make sure the command echo will not be seen
+ # as a prompt itself. The simple obfuscation scheme just
+ # consist of single-quoting each character (for example, the
+ # string "abc" becomes 'a''b''c').
+ quoted_prompt = "".join((map(lambda c: f"'{c}'", self.shell_prompt)))
+ self.run("export PS1={}".format(quoted_prompt))
self.run("dmesg -n 1")
# Prevent the shell from wrapping the commands at 80 columns.
self.run("stty columns 29999")
@@ -110,13 +121,13 @@ class Emulator(object):
self.qemu.sendline(cmd)
if timeout != -1:
timeout *= self.timeout_multiplier
- self.qemu.expect("# ", timeout=timeout)
+ self.qemu.expect(self.shell_prompt, timeout=timeout)
# Remove double carriage return from qemu stdout so str.splitlines()
# works as expected.
output = self.qemu.before.replace("\r\r", "\r").splitlines()[1:]
self.qemu.sendline("echo $?")
- self.qemu.expect("# ")
+ self.qemu.expect(self.shell_prompt)
exit_code = self.qemu.before.splitlines()[2]
exit_code = int(exit_code)
If a program has the string '# ' (i.e. the default shell prompt) in its output, the test execution in the Buildroot runtime test infra is failing. This can be reproduced by adding a single line in a package test script: self.assertRunOk("echo ### this is a string with hashes ###") When executed with, for example, the command: support/testing/run-tests \ -d dl -o output_folder tests.package.test_sometest The test will fail with output: Traceback (most recent call last): File "/buildroot/support/testing/tests/package/test_sometest.py", line 20, in test_run self.assertRunOk("echo ### this is a string with hashes ###") File "/buildroot/support/testing/infra/basetest.py", line 94, in assertRunOk out, exit_code = self.emulator.run(cmd, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/buildroot/support/testing/infra/emulator.py", line 121, in run exit_code = int(exit_code) ^^^^^^^^^^^^^^ ValueError: invalid literal for int() with base 10: '' This issue has been seen with real softwares, for example while writing tests for the dieharder package, which creates report tables formatted with hash characters. See: https://github.com/eddelbuettel/dieharder/blob/3.31.1.4/libdieharder/version.c#L34 See also the output produced by a program invocation with command "dieharder -d 0". This issue has also been seen with dmidecode, producing comments in its output (when simply invoked with "dmidecode"). See: https://git.savannah.gnu.org/cgit/dmidecode.git/tree/dmioutput.c?h=dmidecode-3-5#n30 This issue could technically be seen with program producing MarkDown formatted output (for example "# Header 1"). This issue happen because the test infra emulator.run() method expect the prompt "# " after running a command and while getting the return code. See: https://git.buildroot.org/buildroot/tree/support/testing/infra/emulator.py?h=2023.05#n113 Since the string "# " is quite common, this patch changes the prompt after the emulator.login(), by setting the PS1 variable to a string which is less likely to appear in a normal program output. A small caveat: since there is a command echo, the command setting the new prompt needs to be slightly obfuscated to make sure it will not be detected as an actual shell prompt. The simple obfuscation scheme consist of single-quoting each character (e.g. abc -> 'a''b''c'). Signed-off-by: Julien Olivain <ju.o@free.fr> --- Changes v2 -> v3: - reworded the comment about the prompt obfuscation - rewrote the prompt obfuscation with map() Changes v1 -> v2: - reworded commit log, to mention this issue was also seen while writing a test for the dmidecode package - the patch series also introduce the new test for dmidecode --- support/testing/infra/emulator.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)