diff options
author | Jacek Galowicz <jacek@galowicz.de> | 2022-01-08 18:28:25 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-08 18:28:25 +0100 |
commit | 048fd95f106ef4dca58ff01159207a027ab612d9 (patch) | |
tree | 3231875fa322010481f57a5d0b10102072709903 /nixos/doc/manual/from_md/development | |
parent | 41216b003f541efc899956a97106937e02f4aad2 (diff) | |
parent | 793a2f50f13f0c630cffbbb214f4128254945701 (diff) | |
download | nixpkgs-048fd95f106ef4dca58ff01159207a027ab612d9.tar nixpkgs-048fd95f106ef4dca58ff01159207a027ab612d9.tar.gz nixpkgs-048fd95f106ef4dca58ff01159207a027ab612d9.tar.bz2 nixpkgs-048fd95f106ef4dca58ff01159207a027ab612d9.tar.lz nixpkgs-048fd95f106ef4dca58ff01159207a027ab612d9.tar.xz nixpkgs-048fd95f106ef4dca58ff01159207a027ab612d9.tar.zst nixpkgs-048fd95f106ef4dca58ff01159207a027ab612d9.zip |
Merge pull request #146905 from Synthetica9/failure_mode
nixos/test-driver: add polling_condition
Diffstat (limited to 'nixos/doc/manual/from_md/development')
-rw-r--r-- | nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml | 846 |
1 files changed, 457 insertions, 389 deletions
diff --git a/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml b/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml index 0d523681b63..45c9c40c609 100644 --- a/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml +++ b/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml @@ -117,407 +117,413 @@ if not "Linux" in machine.succeed("uname"): <programlisting language="python"> start_all() </programlisting> - <para> - The following methods are available on machine objects: - </para> - <variablelist> - <varlistentry> - <term> - <literal>start</literal> - </term> - <listitem> - <para> - Start the virtual machine. This method is asynchronous — it - does not wait for the machine to finish booting. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>shutdown</literal> - </term> - <listitem> - <para> - Shut down the machine, waiting for the VM to exit. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>crash</literal> - </term> - <listitem> - <para> - Simulate a sudden power failure, by telling the VM to exit - immediately. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>block</literal> - </term> - <listitem> - <para> - Simulate unplugging the Ethernet cable that connects the - machine to the other machines. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>unblock</literal> - </term> - <listitem> - <para> - Undo the effect of <literal>block</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>screenshot</literal> - </term> - <listitem> - <para> - Take a picture of the display of the virtual machine, in PNG - format. The screenshot is linked from the HTML log. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>get_screen_text_variants</literal> - </term> - <listitem> - <para> - Return a list of different interpretations of what is - currently visible on the machine's screen using optical - character recognition. The number and order of the - interpretations is not specified and is subject to change, but - if no exception is raised at least one will be returned. - </para> - <note> + <section xml:id="ssec-machine-objects"> + <title>Machine objects</title> + <para> + The following methods are available on machine objects: + </para> + <variablelist> + <varlistentry> + <term> + <literal>start</literal> + </term> + <listitem> <para> - This requires passing <literal>enableOCR</literal> to the - test attribute set. + Start the virtual machine. This method is asynchronous — it + does not wait for the machine to finish booting. </para> - </note> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>get_screen_text</literal> - </term> - <listitem> - <para> - Return a textual representation of what is currently visible - on the machine's screen using optical character recognition. - </para> - <note> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>shutdown</literal> + </term> + <listitem> <para> - This requires passing <literal>enableOCR</literal> to the - test attribute set. + Shut down the machine, waiting for the VM to exit. </para> - </note> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>send_monitor_command</literal> - </term> - <listitem> - <para> - Send a command to the QEMU monitor. This is rarely used, but - allows doing stuff such as attaching virtual USB disks to a - running machine. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>send_key</literal> - </term> - <listitem> - <para> - Simulate pressing keys on the virtual keyboard, e.g., - <literal>send_key("ctrl-alt-delete")</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>send_chars</literal> - </term> - <listitem> - <para> - Simulate typing a sequence of characters on the virtual - keyboard, e.g., - <literal>send_chars("foobar\n")</literal> will type - the string <literal>foobar</literal> followed by the Enter - key. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>execute</literal> - </term> - <listitem> - <para> - Execute a shell command, returning a list - <literal>(status, stdout)</literal>. If the command detaches, - it must close stdout, as <literal>execute</literal> will wait - for this to consume all output reliably. This can be achieved - by redirecting stdout to stderr <literal>>&2</literal>, - to <literal>/dev/console</literal>, - <literal>/dev/null</literal> or a file. Examples of detaching - commands are <literal>sleep 365d &</literal>, where the - shell forks a new process that can write to stdout and - <literal>xclip -i</literal>, where the - <literal>xclip</literal> command itself forks without closing - stdout. Takes an optional parameter - <literal>check_return</literal> that defaults to - <literal>True</literal>. Setting this parameter to - <literal>False</literal> will not check for the return code - and return -1 instead. This can be used for commands that shut - down the VM and would therefore break the pipe that would be - used for retrieving the return code. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>succeed</literal> - </term> - <listitem> - <para> - Execute a shell command, raising an exception if the exit - status is not zero, otherwise returning the standard output. - Commands are run with <literal>set -euo pipefail</literal> - set: - </para> - <itemizedlist> - <listitem> - <para> - If several commands are separated by <literal>;</literal> - and one fails, the command as a whole will fail. - </para> - </listitem> - <listitem> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>crash</literal> + </term> + <listitem> + <para> + Simulate a sudden power failure, by telling the VM to exit + immediately. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>block</literal> + </term> + <listitem> + <para> + Simulate unplugging the Ethernet cable that connects the + machine to the other machines. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>unblock</literal> + </term> + <listitem> + <para> + Undo the effect of <literal>block</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>screenshot</literal> + </term> + <listitem> + <para> + Take a picture of the display of the virtual machine, in PNG + format. The screenshot is linked from the HTML log. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>get_screen_text_variants</literal> + </term> + <listitem> + <para> + Return a list of different interpretations of what is + currently visible on the machine's screen using optical + character recognition. The number and order of the + interpretations is not specified and is subject to change, + but if no exception is raised at least one will be returned. + </para> + <note> <para> - For pipelines, the last non-zero exit status will be - returned (if there is one, zero will be returned - otherwise). + This requires passing <literal>enableOCR</literal> to the + test attribute set. </para> - </listitem> - <listitem> + </note> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>get_screen_text</literal> + </term> + <listitem> + <para> + Return a textual representation of what is currently visible + on the machine's screen using optical character recognition. + </para> + <note> <para> - Dereferencing unset variables fail the command. + This requires passing <literal>enableOCR</literal> to the + test attribute set. </para> - </listitem> - <listitem> + </note> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>send_monitor_command</literal> + </term> + <listitem> + <para> + Send a command to the QEMU monitor. This is rarely used, but + allows doing stuff such as attaching virtual USB disks to a + running machine. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>send_key</literal> + </term> + <listitem> + <para> + Simulate pressing keys on the virtual keyboard, e.g., + <literal>send_key("ctrl-alt-delete")</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>send_chars</literal> + </term> + <listitem> + <para> + Simulate typing a sequence of characters on the virtual + keyboard, e.g., + <literal>send_chars("foobar\n")</literal> will + type the string <literal>foobar</literal> followed by the + Enter key. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>execute</literal> + </term> + <listitem> + <para> + Execute a shell command, returning a list + <literal>(status, stdout)</literal>. If the command + detaches, it must close stdout, as + <literal>execute</literal> will wait for this to consume all + output reliably. This can be achieved by redirecting stdout + to stderr <literal>>&2</literal>, to + <literal>/dev/console</literal>, + <literal>/dev/null</literal> or a file. Examples of + detaching commands are <literal>sleep 365d &</literal>, + where the shell forks a new process that can write to stdout + and <literal>xclip -i</literal>, where the + <literal>xclip</literal> command itself forks without + closing stdout. Takes an optional parameter + <literal>check_return</literal> that defaults to + <literal>True</literal>. Setting this parameter to + <literal>False</literal> will not check for the return code + and return -1 instead. This can be used for commands that + shut down the VM and would therefore break the pipe that + would be used for retrieving the return code. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>succeed</literal> + </term> + <listitem> + <para> + Execute a shell command, raising an exception if the exit + status is not zero, otherwise returning the standard output. + Commands are run with <literal>set -euo pipefail</literal> + set: + </para> + <itemizedlist> + <listitem> + <para> + If several commands are separated by + <literal>;</literal> and one fails, the command as a + whole will fail. + </para> + </listitem> + <listitem> + <para> + For pipelines, the last non-zero exit status will be + returned (if there is one, zero will be returned + otherwise). + </para> + </listitem> + <listitem> + <para> + Dereferencing unset variables fail the command. + </para> + </listitem> + <listitem> + <para> + It will wait for stdout to be closed. See + <literal>execute</literal> for the implications. + </para> + </listitem> + </itemizedlist> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>fail</literal> + </term> + <listitem> + <para> + Like <literal>succeed</literal>, but raising an exception if + the command returns a zero status. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_until_succeeds</literal> + </term> + <listitem> + <para> + Repeat a shell command with 1-second intervals until it + succeeds. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_until_fails</literal> + </term> + <listitem> + <para> + Repeat a shell command with 1-second intervals until it + fails. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_for_unit</literal> + </term> + <listitem> + <para> + Wait until the specified systemd unit has reached the + <quote>active</quote> state. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_for_file</literal> + </term> + <listitem> + <para> + Wait until the specified file exists. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_for_open_port</literal> + </term> + <listitem> + <para> + Wait until a process is listening on the given TCP port (on + <literal>localhost</literal>, at least). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_for_closed_port</literal> + </term> + <listitem> + <para> + Wait until nobody is listening on the given TCP port. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_for_x</literal> + </term> + <listitem> + <para> + Wait until the X11 server is accepting connections. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_for_text</literal> + </term> + <listitem> + <para> + Wait until the supplied regular expressions matches the + textual contents of the screen by using optical character + recognition (see <literal>get_screen_text</literal> and + <literal>get_screen_text_variants</literal>). + </para> + <note> <para> - It will wait for stdout to be closed. See - <literal>execute</literal> for the implications. + This requires passing <literal>enableOCR</literal> to the + test attribute set. </para> - </listitem> - </itemizedlist> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>fail</literal> - </term> - <listitem> - <para> - Like <literal>succeed</literal>, but raising an exception if - the command returns a zero status. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_until_succeeds</literal> - </term> - <listitem> - <para> - Repeat a shell command with 1-second intervals until it - succeeds. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_until_fails</literal> - </term> - <listitem> - <para> - Repeat a shell command with 1-second intervals until it fails. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_for_unit</literal> - </term> - <listitem> - <para> - Wait until the specified systemd unit has reached the - <quote>active</quote> state. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_for_file</literal> - </term> - <listitem> - <para> - Wait until the specified file exists. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_for_open_port</literal> - </term> - <listitem> - <para> - Wait until a process is listening on the given TCP port (on - <literal>localhost</literal>, at least). - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_for_closed_port</literal> - </term> - <listitem> - <para> - Wait until nobody is listening on the given TCP port. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_for_x</literal> - </term> - <listitem> - <para> - Wait until the X11 server is accepting connections. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_for_text</literal> - </term> - <listitem> - <para> - Wait until the supplied regular expressions matches the - textual contents of the screen by using optical character - recognition (see <literal>get_screen_text</literal> and - <literal>get_screen_text_variants</literal>). - </para> - <note> + </note> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_for_console_text</literal> + </term> + <listitem> <para> - This requires passing <literal>enableOCR</literal> to the - test attribute set. + Wait until the supplied regular expressions match a line of + the serial console output. This method is useful when OCR is + not possibile or accurate enough. </para> - </note> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_for_console_text</literal> - </term> - <listitem> - <para> - Wait until the supplied regular expressions match a line of - the serial console output. This method is useful when OCR is - not possibile or accurate enough. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>wait_for_window</literal> - </term> - <listitem> - <para> - Wait until an X11 window has appeared whose name matches the - given regular expression, e.g., - <literal>wait_for_window("Terminal")</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>copy_from_host</literal> - </term> - <listitem> - <para> - Copies a file from host to machine, e.g., - <literal>copy_from_host("myfile", "/etc/my/important/file")</literal>. - </para> - <para> - The first argument is the file on the host. The file needs to - be accessible while building the nix derivation. The second - argument is the location of the file on the machine. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>systemctl</literal> - </term> - <listitem> - <para> - Runs <literal>systemctl</literal> commands with optional - support for <literal>systemctl --user</literal> - </para> - <programlisting language="python"> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wait_for_window</literal> + </term> + <listitem> + <para> + Wait until an X11 window has appeared whose name matches the + given regular expression, e.g., + <literal>wait_for_window("Terminal")</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>copy_from_host</literal> + </term> + <listitem> + <para> + Copies a file from host to machine, e.g., + <literal>copy_from_host("myfile", "/etc/my/important/file")</literal>. + </para> + <para> + The first argument is the file on the host. The file needs + to be accessible while building the nix derivation. The + second argument is the location of the file on the machine. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>systemctl</literal> + </term> + <listitem> + <para> + Runs <literal>systemctl</literal> commands with optional + support for <literal>systemctl --user</literal> + </para> + <programlisting language="python"> machine.systemctl("list-jobs --no-pager") # runs `systemctl list-jobs --no-pager` machine.systemctl("list-jobs --no-pager", "any-user") # spawns a shell for `any-user` and runs `systemctl --user list-jobs --no-pager` </programlisting> - </listitem> - </varlistentry> - <varlistentry> - <term> - <literal>shell_interact</literal> - </term> - <listitem> - <para> - Allows you to directly interact with the guest shell. This - should only be used during test development, not in production - tests. Killing the interactive session with - <literal>Ctrl-d</literal> or <literal>Ctrl-c</literal> also - ends the guest session. - </para> - </listitem> - </varlistentry> - </variablelist> - <para> - To test user units declared by - <literal>systemd.user.services</literal> the optional - <literal>user</literal> argument can be used: - </para> - <programlisting language="python"> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>shell_interact</literal> + </term> + <listitem> + <para> + Allows you to directly interact with the guest shell. This + should only be used during test development, not in + production tests. Killing the interactive session with + <literal>Ctrl-d</literal> or <literal>Ctrl-c</literal> also + ends the guest session. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + To test user units declared by + <literal>systemd.user.services</literal> the optional + <literal>user</literal> argument can be used: + </para> + <programlisting language="python"> machine.start() machine.wait_for_x() machine.wait_for_unit("xautolock.service", "x-session-user") </programlisting> - <para> - This applies to <literal>systemctl</literal>, - <literal>get_unit_info</literal>, <literal>wait_for_unit</literal>, - <literal>start_job</literal> and <literal>stop_job</literal>. - </para> - <para> - For faster dev cycles it's also possible to disable the code-linters - (this shouldn't be commited though): - </para> - <programlisting language="bash"> + <para> + This applies to <literal>systemctl</literal>, + <literal>get_unit_info</literal>, + <literal>wait_for_unit</literal>, <literal>start_job</literal> and + <literal>stop_job</literal>. + </para> + <para> + For faster dev cycles it's also possible to disable the + code-linters (this shouldn't be commited though): + </para> + <programlisting language="bash"> import ./make-test-python.nix { skipLint = true; machine = @@ -531,13 +537,13 @@ import ./make-test-python.nix { ''; } </programlisting> - <para> - This will produce a Nix warning at evaluation time. To fully disable - the linter, wrap the test script in comment directives to disable - the Black linter directly (again, don't commit this within the - Nixpkgs repository): - </para> - <programlisting language="bash"> + <para> + This will produce a Nix warning at evaluation time. To fully + disable the linter, wrap the test script in comment directives to + disable the Black linter directly (again, don't commit this within + the Nixpkgs repository): + </para> + <programlisting language="bash"> testScript = '' # fmt: off @@ -545,4 +551,66 @@ import ./make-test-python.nix { # fmt: on ''; </programlisting> + </section> + <section xml:id="ssec-failing-tests-early"> + <title>Failing tests early</title> + <para> + To fail tests early when certain invariables are no longer met + (instead of waiting for the build to time out), the decorator + <literal>polling_condition</literal> is provided. For example, if + we are testing a program <literal>foo</literal> that should not + quit after being started, we might write the following: + </para> + <programlisting language="python"> +@polling_condition +def foo_running(): + machine.succeed("pgrep -x foo") + + +machine.succeed("foo --start") +machine.wait_until_succeeds("pgrep -x foo") + +with foo_running: + ... # Put `foo` through its paces +</programlisting> + <para> + <literal>polling_condition</literal> takes the following + (optional) arguments: + </para> + <para> + <literal>seconds_interval</literal> + </para> + <para> + : specifies how often the condition should be polled: + </para> + <programlisting> +```py +@polling_condition(seconds_interval=10) +def foo_running(): + machine.succeed("pgrep -x foo") +``` +</programlisting> + <para> + <literal>description</literal> + </para> + <para> + : is used in the log when the condition is checked. If this is not + provided, the description is pulled from the docstring of the + function. These two are therefore equivalent: + </para> + <programlisting> +```py +@polling_condition +def foo_running(): + "check that foo is running" + machine.succeed("pgrep -x foo") +``` + +```py +@polling_condition(description="check that foo is running") +def foo_running(): + machine.succeed("pgrep -x foo") +``` +</programlisting> + </section> </section> |