Buildroot Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Yann E. MORIN" <yann.morin.1998@free.fr>
To: Julien Olivain <ju.o@free.fr>
Cc: Ricardo Martincoski <ricardo.martincoski@datacom.com.br>,
	buildroot@buildroot.org
Subject: Re: [Buildroot] [PATCH v2 1/3] support/testing/infra/emulator.py: change the shell prompt before running tests
Date: Tue, 27 Jun 2023 23:21:16 +0200	[thread overview]
Message-ID: <20230627212116.GK646621@scaer> (raw)
In-Reply-To: <802f2f6d2163a5e097b909ac2e13c57a@free.fr>

Julien, All,

On 2023-06-27 21:43 +0200, Julien Olivain spake thusly:
> On 26/06/2023 23:06, Yann E. MORIN wrote:
> >On 2023-06-11 12:45 +0200, Julien Olivain spake thusly:
> >>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 ###")
[--SNIP--]
> >>an actual shell prompt. The prompt is encoded by single-quoting
> >>each character (e.g. abc -> 'a''b''c').
> >That's not really what join() will do. E.g. with your code:
> >    >>> s = "#BRTEST# "
> >    >>> "''".join(s)
> >    "#''B''R''T''E''S''T''#'' "
> I agree doing this, we miss the first and last quote. This is exactly what
> the next line is doing:
>     self.run("export PS1='{}'".format(encoded_prompt))
> Note the extra quotes. If you look in a run-test run log, there will be:
>     # export PS1='#''B''R''T''E''S''T''#'' '
>     #BRTEST# echo $?
>     0

Ah, yeah, so the prompt is not "encoded". Rather, the command setting
the prompt is obfuscated to that it is not itself detected as a prompt
being displayed.

OK, got it.

> This was my initial intent: setting the PS1 without the local echo
> begin caught by pexpect.

Yup.

> If you prefer any other encoding or prompt, please suggest something
> else. I initially tried by temporarily disabling the local echo with
> "stty -echo" but this was creating other issues...

Yeah, I think using a side channel to inform pexpect that a prompt is
actually being displayed, would eventually do the trick. That, combined
with your trick to obfuscate the command setting the prompt:

    # \033_ is APC (Application Program Command),
    # \033\ is ST (String Terminator), which terminates APC
    self.prompt_esc = '\033_BR_COMMAND_FINISHED\033\\'
    # Obfuscate the command setting the prompt, so that it is not
    # itself detected as a prompt being displayed.
    self.run("export PS1='{}# '".format("''".join(self.prompt_esc)))

And then, the emulator would be changed to expect that ANSI escape
sequence; everywhere we expect("# ") or expect(["# ",...]), we switch to
using self.prompt_esc instead or "# "

Totally untested, of course! I have a little doubt about whether the
escape ANSI sequence can be obfuscated that way, though...

[--SNIP--]
> >Anyway, your patch at least breaks tests.package.test_bash...
> The /etc/profile in Buildroot skeleton is overwriting PS1, see:
> https://git.buildroot.org/buildroot/tree/system/skeleton/etc/profile?h=2023.05#n5
> 
> I was able to fix this test_bash by passing the PS1 in another exported
> variable:
> 
>     self.assertRunOk("export BR_PS1=\"$PS1\"")
>     self.emulator.qemu.sendline("bash -il")
>     self.assertRunOk("export PS1=\"${BR_PS1}\"")
> 
> The "bash -il" return code is no longer tested, but I don't think it's
> an issue since the rest of the test covers that.
> 
> If you agree with this workaround, I'll send an updated v3 patch series.

I think we should instead tell bash to not parse the default bashrc et
al.:

    self.assertRunOk("bash -il --init-file /dev/null --rcfile /dev/null")

And this should solve the issue: PS1 is in the environment, so bash will
inherit it.

Regards,
Yann E. MORIN.

> >
> >Regards,
> >Yann E. MORIN.
> >
> >>Signed-off-by: Julien Olivain <ju.o@free.fr>
> >>---
> >>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 | 14 ++++++++++++--
> >> 1 file changed, 12 insertions(+), 2 deletions(-)
> >>
> >>diff --git a/support/testing/infra/emulator.py
> >>b/support/testing/infra/emulator.py
> >>index 02cf486128..390c582e9d 100644
> >>--- a/support/testing/infra/emulator.py
> >>+++ b/support/testing/infra/emulator.py
> >>@@ -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,15 @@ class Emulator(object):
> >>         index = self.qemu.expect(["# ", pexpect.TIMEOUT])
> >>         if index != 0:
> >>             raise SystemError("Cannot login")
> >>+        # Set a special shell prompt while 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 encode or escape it in some way to
> >>+        # make sure the command echo will not be seen as a prompt
> >>+        # itself. The prompt is encoded by single-quoting each
> >>+        # character (e.g. abc -> 'a''b''c').
> >>+        encoded_prompt = "''".join(self.shell_prompt)
> >>+        self.run("export PS1='{}'".format(encoded_prompt))
> >>         self.run("dmesg -n 1")
> >>         # Prevent the shell from wrapping the commands at 80 columns.
> >>         self.run("stty columns 29999")
> >>@@ -110,13 +120,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)
> >>
> >>--
> >>2.41.0
> >>
> >>_______________________________________________
> >>buildroot mailing list
> >>buildroot@buildroot.org
> >>https://lists.buildroot.org/mailman/listinfo/buildroot
> 
> Best regards,
> 
> Julien.

-- 
.-----------------.--------------------.------------------.--------------------.
|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software  Designer | \ / CAMPAIGN     |  ___               |
| +33 561 099 427 `------------.-------:  X  AGAINST      |  \e/  There is no  |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL    |   v   conspiracy.  |
'------------------------------^-------^------------------^--------------------'
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

      reply	other threads:[~2023-06-27 21:21 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-11 10:45 [Buildroot] [PATCH v2 1/3] support/testing/infra/emulator.py: change the shell prompt before running tests Julien Olivain
2023-06-26 20:00 ` [Buildroot] [PATCH v2 2/3] support/testing/tests/package/test_dieharder.py: new runtime test Julien Olivain
2023-06-26 20:01 ` [Buildroot] [PATCH v2 3/3] support/testing/tests/package/test_dmidecode.py: " Julien Olivain
2023-06-26 21:06 ` [Buildroot] [PATCH v2 1/3] support/testing/infra/emulator.py: change the shell prompt before running tests Yann E. MORIN
2023-06-27 19:43   ` Julien Olivain
2023-06-27 21:21     ` Yann E. MORIN [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230627212116.GK646621@scaer \
    --to=yann.morin.1998@free.fr \
    --cc=buildroot@buildroot.org \
    --cc=ju.o@free.fr \
    --cc=ricardo.martincoski@datacom.com.br \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox