Merge pull request #165752 from helsinki-systems/feat/test-runner-send-serial
nixos/test-runner: Allow writing to qemu stdin
This commit is contained in:
commit
5a650acbb1
3 changed files with 70 additions and 1 deletions
|
@ -158,6 +158,12 @@ The following methods are available on machine objects:
|
||||||
e.g., `send_chars("foobar\n")` will type the string `foobar`
|
e.g., `send_chars("foobar\n")` will type the string `foobar`
|
||||||
followed by the Enter key.
|
followed by the Enter key.
|
||||||
|
|
||||||
|
`send_console`
|
||||||
|
|
||||||
|
: Send keys to the kernel console. This allows interaction with the systemd
|
||||||
|
emergency mode, for example. Takes a string that is sent, e.g.,
|
||||||
|
`send_console("\n\nsystemctl default\n")`.
|
||||||
|
|
||||||
`execute`
|
`execute`
|
||||||
|
|
||||||
: Execute a shell command, returning a list `(status, stdout)`.
|
: Execute a shell command, returning a list `(status, stdout)`.
|
||||||
|
@ -272,6 +278,13 @@ The following methods are available on machine objects:
|
||||||
Killing the interactive session with `Ctrl-d` or `Ctrl-c` also ends
|
Killing the interactive session with `Ctrl-d` or `Ctrl-c` also ends
|
||||||
the guest session.
|
the guest session.
|
||||||
|
|
||||||
|
`console_interact`
|
||||||
|
|
||||||
|
: Allows you to directly interact with QEMU's stdin. This should
|
||||||
|
only be used during test development, not in production tests.
|
||||||
|
Output from QEMU is only read line-wise. `Ctrl-c` kills QEMU and
|
||||||
|
`Ctrl-d` closes console and returns to the test runner.
|
||||||
|
|
||||||
To test user units declared by `systemd.user.services` the optional
|
To test user units declared by `systemd.user.services` the optional
|
||||||
`user` argument can be used:
|
`user` argument can be used:
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,19 @@ start_all()
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<literal>send_console</literal>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Send keys to the kernel console. This allows interaction
|
||||||
|
with the systemd emergency mode, for example. Takes a string
|
||||||
|
that is sent, e.g.,
|
||||||
|
<literal>send_console("\n\nsystemctl default\n")</literal>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
<literal>execute</literal>
|
<literal>execute</literal>
|
||||||
|
@ -502,6 +515,21 @@ machine.systemctl("list-jobs --no-pager", "any-user") # spaw
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<literal>console_interact</literal>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Allows you to directly interact with QEMU’s stdin. This
|
||||||
|
should only be used during test development, not in
|
||||||
|
production tests. Output from QEMU is only read line-wise.
|
||||||
|
<literal>Ctrl-c</literal> kills QEMU and
|
||||||
|
<literal>Ctrl-d</literal> closes console and returns to the
|
||||||
|
test runner.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
<para>
|
<para>
|
||||||
To test user units declared by
|
To test user units declared by
|
||||||
|
|
|
@ -198,7 +198,7 @@ class StartCommand:
|
||||||
) -> subprocess.Popen:
|
) -> subprocess.Popen:
|
||||||
return subprocess.Popen(
|
return subprocess.Popen(
|
||||||
self.cmd(monitor_socket_path, shell_socket_path),
|
self.cmd(monitor_socket_path, shell_socket_path),
|
||||||
stdin=subprocess.DEVNULL,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
shell=True,
|
shell=True,
|
||||||
|
@ -558,6 +558,28 @@ class Machine:
|
||||||
pass_fds=[self.shell.fileno()],
|
pass_fds=[self.shell.fileno()],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def console_interact(self) -> None:
|
||||||
|
"""Allows you to interact with QEMU's stdin
|
||||||
|
|
||||||
|
The shell can be exited with Ctrl+D. Note that Ctrl+C is not allowed to be used.
|
||||||
|
QEMU's stdout is read line-wise.
|
||||||
|
|
||||||
|
Should only be used during test development, not in the production test."""
|
||||||
|
self.log("Terminal is ready (there is no prompt):")
|
||||||
|
|
||||||
|
assert self.process
|
||||||
|
assert self.process.stdin
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
char = sys.stdin.buffer.read(1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
break
|
||||||
|
if char == b"": # ctrl+d
|
||||||
|
self.log("Closing connection to the console")
|
||||||
|
break
|
||||||
|
self.send_console(char.decode())
|
||||||
|
|
||||||
def succeed(self, *commands: str, timeout: Optional[int] = None) -> str:
|
def succeed(self, *commands: str, timeout: Optional[int] = None) -> str:
|
||||||
"""Execute each command and check that it succeeds."""
|
"""Execute each command and check that it succeeds."""
|
||||||
output = ""
|
output = ""
|
||||||
|
@ -834,6 +856,12 @@ class Machine:
|
||||||
self.send_monitor_command("sendkey {}".format(key))
|
self.send_monitor_command("sendkey {}".format(key))
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
def send_console(self, chars: str) -> None:
|
||||||
|
assert self.process
|
||||||
|
assert self.process.stdin
|
||||||
|
self.process.stdin.write(chars.encode())
|
||||||
|
self.process.stdin.flush()
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
if self.booted:
|
if self.booted:
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue