meson icon indicating copy to clipboard operation
meson copied to clipboard

Add should_error kwarg to test()

Open gerioldman opened this issue 1 year ago • 5 comments

This PR adds a new kwarg named 'should_error' to the test call that is similar to should_fail. It behaves the same, the only difference is that it expects error instead of fail.

The use case is that I am running some some tests where I purposefully inject failures that end up as 'Bail out!' with TAP, so the test result is expected to be error.

gerioldman avatar Aug 18 '24 14:08 gerioldman

should_fail is equivalent to TAP's "todo" status. How does should_error map to TAP?

eli-schwartz avatar Aug 20 '24 01:08 eli-schwartz

@eli-schwartz

If should_fail maps to "todo", then I guess I've been abusing how should_fail works. I think should_error would map to an expected 'Bail out!', which is a test ended due to a fatal error. I guess it can be interpreted as "todo" as well.

My use case is that I have tests I intentionally inject with failures/errors and I expect the test to fail to see if the failure is caught. In which case, "failing" actually means pass, in the sense that Meson returns 0, not failing the CI job.

should_fail does this for failures, so Meson returns 0, but there is no way to do this currently for errors.

Example CI run with this PR's content: https://gitlab.com/gergo.krisztian/opentestloader/-/jobs/7608089075

gerioldman avatar Aug 20 '24 04:08 gerioldman

If should_fail maps to "todo", then I guess I've been abusing how should_fail works. I think should_error would map to an expected 'Bail out!', which is a test ended due to a fatal error. I guess it can be interpreted as "todo" as well.

Semantically, a should_fail results in meson logging the test result as an "Expected Fail:" instead of an "Ok:", and if the test starts passing it is logged as an "Unexpected Pass:", again instead of an actual "Ok:".

The reason there are 3 different statuses for this is because the "Expected Fail" list is a list of things you should be reminded to take care of at some point and "Unexpected Pass:" is stuff you have fixed and need to remove the todo note so that you start checking it again.

...

On a practical level, "Expected Fail" doesn't result in a test results failure and "Unexpected Pass" does, which means setting should_fail effectively inverts the exit code.

I am discontented with the confusion this causes. I would like to see should_fail deprecated, have it renamed to expected_fail, and have a brand new success_returncode implemented for people who want to positively test (result: "Ok") that a command binary returns errors when run.

Also, probably, expected_fail should only be permitted when the test itself is run via protocol: 'exitcode'. e.g. users of TAP should be relying on emitting "todo" markers to flag this, and users who simply want to purposefully inject test failures would be better off with asserting that a return code other than 0 should be considered the "Ok" condition.

eli-schwartz avatar Aug 20 '24 04:08 eli-schwartz

@eli-schwartz Is the current commit what you had in mind?

gerioldman avatar Sep 04 '24 15:09 gerioldman

Fixes #10479

bonzini avatar Feb 14 '25 22:02 bonzini

@gerioldman can you please rebase?

bonzini avatar Apr 08 '25 17:04 bonzini

@gerioldman can you please rebase?

I did, I will check the CI failures tomorrow.

gerioldman avatar Apr 08 '25 22:04 gerioldman

It's just a stray should_fail in test\ cases/rust/9\ unit\ tests/meson.build.

bonzini avatar Apr 09 '25 13:04 bonzini

The remaining CI failure is unrelated and caused by LLVM static libraries.

bonzini avatar Apr 10 '25 11:04 bonzini

Should specifying both expected_errorcode and should/expected_fail at the same time be an error?

Combining both is quite confusing at least to me. The former is "I need this exact thing to happen" whereas the latter is "I need the opposite of this exact thing to happen". The combination of those is "the error code must be anything except 42". Is that ever meaningful?

jpakkane avatar Apr 15 '25 08:04 jpakkane

Based on the discussions on this PR, should/expected_fail is used for saying: "I know this test is failing, Meson should have exit code 0 if this test fails, and say it is an expected failure, not a pass.", while expected_exitcode is used for specifying what exitcode the accept for a test pass. So the combination would be the very rare situation of: "I have a test that expects 15 as exitcode, but returns 1 right now, and it is a expected fail."

gerioldman avatar Apr 17 '25 16:04 gerioldman

Asking again:

Should specifying both expected_errorcode and should/expected_fail at the same time be an error?

jpakkane avatar May 06 '25 18:05 jpakkane

Should specifying both expected_errorcode and should/expected_fail at the same time be an error?

No, for example a test could have expected_errorcode of 1 but it currently returns 0; then you make it expected_fail: true so that it to shows as an XFAIL rather than a PASS.

In other words expected_errorcode is about the desired behavior of the program, while expected_fail records known bugs.

bonzini avatar May 06 '25 18:05 bonzini

@gerioldman apologies really but I noticed one more change needed (IMO). The handling of error codes 77 and 99 is a bit messy, they're not usable anymore if expected_exitcode is provided. I can see why you did it that way, but skipping tests can still be valuable and I am afraid that people will lose that by using expected_exitcode: 0 innocently.

My suggestion is

elif self.returncode == (self.expected_exitcode or 0):
    self.res = TestResult.OK
elif self.returncode == GNU_SKIP_RETURNCODE:
   ...
else:
    self.res = TestResult.FAIL

I should have noticed this before, sorry.

bonzini avatar Jun 19 '25 10:06 bonzini

Damn, I overlooked that. I will check.

gerioldman avatar Jun 19 '25 11:06 gerioldman

@bonzini Can you check the last commit?

gerioldman avatar Jul 01 '25 22:07 gerioldman

It doesn't use the same logic as the version with the "match" statement (b3af6e9) and I am not sure if it's intentional. Is there a reason why you didn't just rewrite the match statement as a chain of "if"s?

bonzini avatar Jul 19 '25 17:07 bonzini

Sorry for the late reply, I had some other priorities. I don't exactly remember why I went with match-case, I can switch it back to if's. As for why the logic is different, the snippet you shared would make a 0 returncode pass as OK if expected_exitcode was specified. I think that's incorrect.

gerioldman avatar Aug 06 '25 20:08 gerioldman