Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement check result key, checks affect test result by default #3239

Merged
merged 35 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c872c2d
Implement check result key feature
martinhoyer Oct 9, 2024
897e01e
Add check-result spec and release note
martinhoyer Oct 16, 2024
f75ec1c
Move and modify check schema
martinhoyer Oct 16, 2024
bd7aac8
Fix doc generation
martinhoyer Oct 16, 2024
855cd0e
Add is_enum to plugins doc generate script
happz Oct 16, 2024
8207ca6
Fix result interpretation, notes, tests
martinhoyer Oct 18, 2024
cca13d1
Do not interpret any result with CUSTOM interpret
martinhoyer Oct 21, 2024
d5d7629
Addressing comments
martinhoyer Oct 21, 2024
0c8031e
Add note for running one check multiple times
martinhoyer Oct 21, 2024
d0b5f7e
Add description to check-result tests
martinhoyer Oct 21, 2024
04e7aed
fixup! Addressing comments
martinhoyer Oct 21, 2024
84ffa11
Move the result definition list to spec
martinhoyer Oct 21, 2024
32917bd
Addressing comments for tests, spec
martinhoyer Oct 21, 2024
1ecc935
[PoC] use metadata.choices for the enums
martinhoyer Oct 22, 2024
83e16e3
Improve xfail check result handling
martinhoyer Oct 22, 2024
e0970ee
A minor spec wording adjustment
psss Oct 23, 2024
6389548
Small release notes adjustment, fix a typo
psss Oct 23, 2024
0e36df1
Add missing coversions to and from spec
psss Oct 23, 2024
7bc7973
Define the `to_minimal_spec()` method as well
psss Oct 23, 2024
b7bdfa4
Improve tests
martinhoyer Oct 23, 2024
f4cc82a
Add missing parameter in docstring
martinhoyer Oct 23, 2024
d7c37c8
Fix avc, dmesg tests expecting exit code 0
martinhoyer Oct 23, 2024
2296307
Addressing comments
martinhoyer Oct 24, 2024
2830254
fixup! Fix avc, dmesg tests expecting exit code 0
martinhoyer Oct 24, 2024
f71767a
Addressing yet more valuable comments
martinhoyer Oct 24, 2024
96c03df
Aggregating check results, attempt 1
martinhoyer Oct 24, 2024
308f78a
Unit tests attempt 1
martinhoyer Oct 24, 2024
03877ba
Aggregating check results first
martinhoyer Oct 24, 2024
21181dd
Aggregate check results attempt 2
martinhoyer Oct 24, 2024
4b1972a
Aggregate check results attempt 3
psss Oct 25, 2024
3f75c53
Adjust tests accordingly
psss Oct 25, 2024
45889d7
Adjust tests accordingly
psss Oct 25, 2024
b6f152b
Drop `aggregate_check_results` and related test
psss Oct 25, 2024
cd0527d
Add warning, fix typos, extend release note a bit
psss Oct 25, 2024
64e2b0b
A couple of necessary test output check adjustments
psss Oct 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/releases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ A new :ref:`test-runner` section has been added to the tmt
:ref:`guide`. It describes some important differences between
running tests on a :ref:`user-system` and scheduling test jobs in

Test checks affect the overall test result by default. The
:ref:`/spec/tests/check` specification now supports a new
``result`` key for individual checks. This attribute allows users
to control how the result of each check affects the overall test
result. Please note that tests, which were previously passing
with failing checks will now fail by default, unless the ``xfail``
or ``info`` is added.

Each execution of ``tmt-report-result`` command inside a shell
test will now create a tmt subresult. The main result outcome is
reduced from all subresults outcomes. If ``tmt-report-result`` is
Expand Down
10 changes: 9 additions & 1 deletion docs/scripts/generate-plugins.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3

import dataclasses
import enum
import sys
import textwrap
from typing import Any
Expand Down Expand Up @@ -56,7 +57,7 @@ def _is_inherited(

# TODO: for now, it's a list, but inspecting the actual tree of classes
# would be more generic. It's good enough for now.
return field.name in ('name', 'where', 'order', 'summary', 'enabled')
return field.name in ('name', 'where', 'order', 'summary', 'enabled', 'result')


def container_ignored_fields(container: ContainerClass) -> list[str]:
Expand Down Expand Up @@ -106,6 +107,12 @@ def container_intrinsic_fields(container: ContainerClass) -> list[str]:
return field_names


def is_enum(value: Any) -> bool:
""" Find out whether a given value is an enum member """

return isinstance(value, enum.Enum)


def _create_step_plugin_iterator(registry: tmt.plugins.PluginRegistry[tmt.steps.Method]):
""" Create iterator over plugins of a given registry """

Expand Down Expand Up @@ -184,6 +191,7 @@ def main() -> None:
STEP=step_name,
PLUGINS=plugin_generator,
REVIEWED_PLUGINS=REVIEWED_PLUGINS,
is_enum=is_enum,
container_fields=tmt.utils.container_fields,
container_field=tmt.utils.container_field,
container_ignored_fields=container_ignored_fields,
Expand Down
10 changes: 7 additions & 3 deletions docs/templates/plugins.rst.j2
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
{{ option }}: ``{{ metadata.metavar }}``
{% elif metadata.default is boolean %}
{{ option }}: ``true|false``
{% elif metadata.choices %}
{{ option }}: ``{{ metadata.choices }}``
{% else %}
{{ option }}:
{% endif %}
Expand All @@ -27,11 +29,13 @@
{% elif actual_default is sequence %}
{% if not actual_default %}
Default: *not set*
{% else %}
{% else %}
Default: {% for default_item in actual_default %}``{{ default_item.pattern | default(default_item) }}``{% if not loop.last %}, {% endif %}{% endfor %}
{% endif %}
{% elif is_enum(actual_default) %}
Default: ``{{ actual_default.value }}``
psss marked this conversation as resolved.
Show resolved Hide resolved
{% else %}
{% set _ = LOGGER.warn("%s/%s.%s: could not render default value, '%s'" | format(STEP, plugin_id, field_name, actual_default)) %}
{% set _ = LOGGER.warn("%s/%s.%s: could not render default value, '%s'" | format(STEP, plugin_id, field_name, actual_default), shift=0) %}
Default: *could not render default value correctly*
{% endif %}
{% endif %}
Expand Down Expand Up @@ -71,7 +75,7 @@ The following keys are accepted by all plugins of the ``{{ STEP }}`` step.
Please, be aware that the documentation below is a work in progress. We are
working on fixing it, adding missing bits and generally making it better.
Also, it was originally used for command line help only, therefore the
formatting is often suboptional.
formatting is often suboptimal.
{% endif %}

{% if PLUGIN.__doc__ %}
Expand Down
39 changes: 39 additions & 0 deletions spec/tests/check.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,29 @@ description: |
panic detection, core dump collection or collection of system
logs.

By default, the check results affect the overall test outcome.
psss marked this conversation as resolved.
Show resolved Hide resolved
To change this behaviour, use the ``result`` key, which accepts
the following values:

respect
The check result is respected and affects the overall
test result. This is the default.

xfail
The check result is expected to fail (pass becomes
fail and vice-versa).

info
The check result is treated as an informational
message and does not affect the overall test result.

.. warning::

Note that running one check multiple times for the same
test is not yet supported.

.. versionchanged:: 1.38.0 the ``result`` key added

See :ref:`/plugins/test-checks` for the list of available checks.

example:
Expand All @@ -37,7 +60,23 @@ example:
- how: test-inspector
enable: false

- |
# Expect the AVC check to fail
check:
- how: avc
result: xfail
- how: dmesg
result: respect

- |
# Treat the dmesg check as informational only
check:
- how: dmesg
result: info

link:
- implemented-by: /tmt/checks
- implemented-by: /tmt/result.py
- verified-by: /tests/test/check/avc
- verified-by: /tests/test/check/dmesg
- verified-by: /tests/execute/result/check
2 changes: 1 addition & 1 deletion tests/discover/tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ rlJournalStart
rlRun -s "tmt run --id $workdir -vvv $plan"
rlAssertGrep "package: 1 package requested" "$rlRun_LOG" -F
rlAssertGrep "test: Concise summary" "$rlRun_LOG" -F
rlAssertGrep '00:00:00 pass /first (on default-0) (original result: fail) [1/2]' "$rlRun_LOG" -F
rlAssertGrep '00:00:00 pass /first (on default-0) (test failed as expected, original test result: fail) [1/2]' "$rlRun_LOG" -F
rlAssertGrep '00:00:00 pass /second (on default-0) [2/2]' "$rlRun_LOG" -F
rlPhaseEnd

Expand Down
23 changes: 12 additions & 11 deletions tests/execute/result/basic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ run()
if [ -z "${orig}" ]; then # No original result provided
rlAssertGrep "${res} ${tn}$" $rlRun_LOG
else
rlAssertGrep "${res} ${tn} (original result: ${orig})$" $rlRun_LOG
rlAssertGrep "${res} ${tn} (.*original test result: ${orig}.*)$" $rlRun_LOG
fi

echo
Expand All @@ -38,7 +38,7 @@ rlJournalStart
run "errr" "/test/error" "" 2
run "pass" "/test/xfail-fail" "fail" 0
run "fail" "/test/xfail-pass" "pass" 1
psss marked this conversation as resolved.
Show resolved Hide resolved
run "errr" "/test/xfail-error" "error" 2
run "errr" "/test/xfail-error" "" 2
run "pass" "/test/always-pass" "fail" 0
run "info" "/test/always-info" "pass" 0
run "warn" "/test/always-warn" "pass" 1
Expand All @@ -58,18 +58,18 @@ rlJournalStart
rlAssertGrep "$line" "$rlRun_LOG" -F
fi
done <<-EOF
00:00:00 errr /test/always-error (on default-0) (original result: pass) [1/12]
00:00:00 fail /test/always-fail (on default-0) (original result: pass) [2/12]
00:00:00 info /test/always-info (on default-0) (original result: pass) [3/12]
00:00:00 pass /test/always-pass (on default-0) (original result: fail) [4/12]
00:00:00 warn /test/always-warn (on default-0) (original result: pass) [5/12]
00:00:00 errr /test/always-error (on default-0) (test result overridden: error, original test result: pass) [1/12]
00:00:00 fail /test/always-fail (on default-0) (test result overridden: fail, original test result: pass) [2/12]
00:00:00 info /test/always-info (on default-0) (test result overridden: info, original test result: pass) [3/12]
00:00:00 pass /test/always-pass (on default-0) (test result overridden: pass, original test result: fail) [4/12]
00:00:00 warn /test/always-warn (on default-0) (test result overridden: warn, original test result: pass) [5/12]
00:00:00 errr /test/error (on default-0) [6/12]
00:00:01 errr /test/error-timeout (on default-0) (timeout) [7/12]
00:00:00 fail /test/fail (on default-0) [8/12]
00:00:00 pass /test/pass (on default-0) [9/12]
00:00:00 errr /test/xfail-error (on default-0) (original result: error) [10/12]
00:00:00 pass /test/xfail-fail (on default-0) (original result: fail) [11/12]
00:00:00 fail /test/xfail-pass (on default-0) (original result: pass) [12/12]
00:00:00 errr /test/xfail-error (on default-0) [10/12]
00:00:00 pass /test/xfail-fail (on default-0) (test failed as expected, original test result: fail) [11/12]
00:00:00 fail /test/xfail-pass (on default-0) (test was expected to fail, original test result: pass) [12/12]
EOF
rlPhaseEnd

Expand All @@ -78,7 +78,8 @@ EOF
rlRun -s "tmt run --id \${run} --scratch --until execute tests -n /xfail-with-reboot provision --how container execute -v 2>&1 >/dev/null"
EXPECTED=$(cat <<EOF
00:00:00 /test/xfail-with-reboot [1/1]
00:00:00 pass /test/xfail-with-reboot (on default-0) (original result: fail) [1/1]
00:00:00 pass /test/xfail-with-reboot (on default-0) (test failed as expected, original test result: fail) [1/1]

EOF
)
rlAssertEquals "Output matches the expectation" "$EXPECTED" "$(grep /test/xfail-with-reboot $rlRun_LOG)"
Expand Down
29 changes: 29 additions & 0 deletions tests/execute/result/check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash
. /usr/share/beakerlib/beakerlib.sh || exit 1

rlJournalStart
rlPhaseStartSetup
rlRun "run=\$(mktemp -d)" 0 "Create run directory"
rlRun "PROVISION_HOW=${PROVISION_HOW:-virtual}"
rlRun "pushd check"
rlRun "set -o pipefail"
rlPhaseEnd

rlPhaseStartTest "Check Results"
rlRun "tmt run -av --id $run provision --how $PROVISION_HOW" 1
rlRun -s "tmt run --id $run report -v" 1

rlAssertGrep "pass /test/check-fail-info (check 'dmesg' is informational)" "$rlRun_LOG"
rlAssertGrep "fail /test/check-fail-respect (check 'dmesg' failed, original test result: pass)" "$rlRun_LOG"
rlAssertGrep "pass /test/check-override (check 'dmesg' failed, test result overridden: pass)" "$rlRun_LOG"
rlAssertGrep "pass /test/check-pass" "$rlRun_LOG"
rlAssertGrep "fail /test/check-pass-test-xfail (test was expected to fail, original test result: pass)" "$rlRun_LOG"
rlAssertGrep "pass /test/check-xfail-fail (check 'dmesg' failed as expected)" "$rlRun_LOG"
rlAssertGrep "fail /test/check-xfail-pass (check 'dmesg' did not fail as expected, original test result: pass)" "$rlRun_LOG"
rlPhaseEnd

rlPhaseStartCleanup
rlRun "popd"
rlRun "rm -r ${run}" 0 "Remove run directory"
rlPhaseEnd
rlJournalEnd
1 change: 1 addition & 0 deletions tests/execute/result/check/.fmf/version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
89 changes: 89 additions & 0 deletions tests/execute/result/check/test.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
summary: Tests for check results behaviour
description: Verify that check results are correctly interpreted and affect test results
framework: shell
duration: 1m

/check-pass:
summary: Test with passing checks
description: |
Expected outcome: PASS (test passes, check passes)
test: echo "Test passed"
check:
- how: dmesg
result: respect

/check-pass-test-xfail:
summary: Everything passing but failure expected
description: |
Expected outcome: FAIL (test passes, check passes, but fail is expected)
test: echo "Test passed"
check:
- how: dmesg
result: respect
result: xfail

/check-fail-respect:
summary: Test with failing dmesg check (respect)
description: |
Expected outcome: FAIL (test passes, but check fails and is respected)
test: echo "Fail Test Check Pattern" | tee /dev/kmsg
check:
- how: dmesg
failure-pattern: Fail Test Check Pattern

/check-fail-info:
summary: Test with failing dmesg check (info)
description: |
Expected outcome: PASS (test passes, check fails, but should be just info)
test: echo "Fail Test Check Pattern" | tee /dev/kmsg
check:
- how: dmesg
failure-pattern: Fail Test Check Pattern
result: info

/check-xfail-pass:
summary: Test with passing dmesg check (xfail)
description: |
Expected outcome: FAIL (test passes, check passes but xfail expects it to fail)
test: echo "Test passed"
check:
- how: dmesg
result: xfail

/check-xfail-fail:
summary: Test with failing dmesg check (xfail)
description: |
Expected outcome: PASS (test passes, check fails but xfail expects it to fail)
test: echo "Fail Test Check Pattern" | tee /dev/kmsg
check:
- how: dmesg
failure-pattern: Fail Test Check Pattern
result: xfail

/check-multiple:
summary: Test with multiple checks with different result interpretations
description: |
Expected outcome: FAIL (first dmesg check fails and is respected, second dmesg check
passes but xfail expects it to fail, third failing dmesg check is just info)"
test: echo "Fail Test Check Pattern" | tee /dev/kmsg
check:
- how: dmesg
failure-pattern: Fail Test Check Pattern
result: respect
- how: dmesg
result: xfail
- how: dmesg
failure-pattern: Fail Test Check Pattern
result: info
enabled: false # TODO: handle multiple checks with same 'name'/'how'

/check-override:
summary: Test with failing dmesg check but overridden by test result
description: |
Expected outcome: PASS (test passes, check fails but is overridden by 'result: pass')
test: echo "Fail Test Check Pattern" | tee /dev/kmsg
result: pass
check:
- how: dmesg
failure-pattern: Fail Test Check Pattern
result: respect
7 changes: 7 additions & 0 deletions tests/execute/result/main.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@
/subresults:
summary: Multiple calls to tmt-report-result should generate tmt subresults
test: ./subresults.sh
/check:
summary: Test check result interpretations
test: ./check.sh
tag+:
- provision-only
- provision-local
- provision-virtual
2 changes: 1 addition & 1 deletion tests/report/html/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ rlJournalStart
grep -B 1 "/test/$test_name_suffix</td>" $HTML | tee $tmp/$test_name_suffix
rlAssertGrep 'class="result pass">pass</td>' $tmp/$test_name_suffix -F
sed -e "/name\">\/test\/$test_name_suffix/,/\/tr/!d" $HTML | tee $tmp/$test_name_suffix-note
rlAssertGrep '<td class="note">original result: fail</td>' $tmp/$test_name_suffix-note -F
rlAssertGrep '<td class="note">test failed as expected, original test result: fail</td>' $tmp/$test_name_suffix-note -F
rlPhaseEnd

if [ "$option" = "" ]; then
Expand Down
2 changes: 1 addition & 1 deletion tests/test/check/test-avc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ rlJournalStart
rlPhaseEnd

rlPhaseStartTest "Run /avc tests with $PROVISION_HOW"
rlRun "tmt -c provision_method=$PROVISION_HOW run --id $run --scratch -a -vvv provision -h $PROVISION_HOW test -n /avc"
rlRun "tmt -c provision_method=$PROVISION_HOW run --id $run --scratch -a -vvv provision -h $PROVISION_HOW test -n /avc" "1"
rlRun "cat $results"
rlPhaseEnd

Expand Down
4 changes: 2 additions & 2 deletions tests/test/check/test-dmesg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ rlJournalStart
rlRun "dump_before=$segfault/checks/dmesg-before-test.txt"
rlRun "dump_after=$segfault/checks/dmesg-after-test.txt"

rlRun "tmt run --id $run --scratch -a -vv provision -h $PROVISION_HOW test -n /dmesg/segfault"
rlRun "tmt run --id $run --scratch -a -vv provision -h $PROVISION_HOW test -n /dmesg/segfault" "1"
rlRun "cat $results"

assert_check_result "dmesg as a before-test should pass" "pass" "before-test" "segfault"
Expand All @@ -84,7 +84,7 @@ rlJournalStart
rlRun "dump_before=$custom_patterns/checks/dmesg-before-test.txt"
rlRun "dump_after=$custom_patterns/checks/dmesg-after-test.txt"

rlRun "tmt run --id $run --scratch -a -vv provision -h $PROVISION_HOW test -n /dmesg/custom-patterns"
rlRun "tmt run --id $run --scratch -a -vv provision -h $PROVISION_HOW test -n /dmesg/custom-patterns" "1"
rlRun "cat $results"

assert_check_result "dmesg as a before-test should fail" "fail" "before-test" "custom-patterns"
Expand Down
Loading
Loading