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 a simple test filter #35

Merged
merged 4 commits into from
Jan 20, 2023
Merged

Implement a simple test filter #35

merged 4 commits into from
Jan 20, 2023

Conversation

yamt
Copy link
Contributor

@yamt yamt commented Dec 19, 2022

cf. #29

@yamt yamt force-pushed the skip branch 5 times, most recently from 41758ae to 70075c3 Compare December 19, 2022 08:19
README.md Outdated
@@ -38,6 +38,16 @@ python3 test-runner/wasi_test_runner.py
-r adapters/wasmtime.sh # path to a runtime adapter
```

Optianally you can specify test cases to skip with the `--filter` option.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Optianally you can specify test cases to skip with the `--filter` option.
Optionally you can specify test cases to skip with the `--filter` option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

README.md Outdated
python3 test-runner/wasi_test_runner.py \
-t ./tests/assemblyscript/testsuite/ `# path to folders containing .wasm test files` \
./tests/c/testsuite/ \
--filter examples/skip.json
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
--filter examples/skip.json
--filter examples/skip.json \

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -54,6 +54,7 @@ def finalize(self, version: RuntimeVersion) -> None:
print(f" Total: {suite.test_count}")
self._print_pass(f" Passed: {suite.pass_count}")
self._print_fail(f" Failed: {suite.fail_count}")
print(f" Skipped: {suite.skip_count}")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
print(f" Skipped: {suite.skip_count}")
self._print_skip(f" Skipped: {suite.skip_count}")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

with patch("glob.glob", return_value=test_paths):
suite = tsr.run_tests_from_test_suite("my-path", runtime, validators, reporters) # type: ignore
suite = tsr.run_tests_from_test_suite("my-path", runtime, validators, reporters, filters) # type: ignore
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we validate if filters actually were called?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be also good to validate the case when the filter returns False and in that case the test is skipped

@@ -0,0 +1,5 @@
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we actually need such a detailed filters for now. Initially I was thinking of the following requirements:

  • being able to do both: include and exclude tests (e.g. --filter-include ".*thread.*" --filter-exclude ".*open.*")
  • pass regular expressions so we can e.g. disable the whole testsuite (something like --filter-exclude "WASI C tests.*")

But I'm curious what are your thoughts on that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my intention is to implement something simplest first. (regex etc is more complex and advanced in my taste.)

also i think it makes sense to have a filter in a file because i guess it's almost static for a given runtime.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I don't suggest implementing all that at once, but I'd like us to think a bit about the API before we move forward. The proposed API of the JSON file only allows for disabling tests, and I'm afraid that if we want to add more features (like the ones mentioned above) we'll either have to make backward-incompatible changes or make the API inconsistent. As I said, we don't have to implement everything in the first iteration, but at least having placeholders would probably simplify further development.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i feel compatibility concern is not too important at this point.

also, your requirements are not clear to me.
if you explain it a bit more, maybe i can suggest a schema.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure; so first of all, I think we should be able to allow users to both select exclusion and inclusion filter (at the moment only the exclusion is possible). Also, we might allow for wildcard/regex, but I assume this could be just a feature request for the future, and we can implement it in the future; just an idea (although feel free to come up with something different):

{
  "include": [], // if empty, all tests are included
  "exclude/ignore(whatever sounds better)": [] // if empty, none of the tests are excluded
}

Element in the array could be a full path to a test, e.g. WASI C tests.clock_getres-monotonic, so we can in the future implement wildcards to only enable clock_getres tests, with: WASI C tests.clock_getres*.

As I said, this is just an example schema to explain what I mean; please let me know if it's clear what we try to achieve here and share your ideas.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my suggestion for this PR:

  • rename --filter option to --exclude-filter
  • no changes to schema
  • we can consider adding --include-filter, --exclude-regex-filter etc later when/if necessary.

Copy link
Collaborator

@loganek loganek Jan 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename --filter option to --exclude-filter

Given we already define filters in the JSON file, I don't know if there's a need for having two cli parameters, or instead could we have just one (--filter) and update the schema so it allows for specifying both inclusion and exclusion - I don't have a strong opinion; just a thought, as I haven't seen them separate in other farameworks.

no changes to schema

Not sure if we actually need a nested structure here (testsuite->tests); if we implement regex/glob we could probably just have a list of strings? We can start with this one as it might seem a bit simpler but once we update it, we'll have to update all the consumers as well (not sure how many runtimes will onboard by then though).

I'm also not 100% sure about file vs cli parameter. Whereas I see the benefit you mentioned above, I think it
doesn't matter that much for runtimes as they'll have their own CI scripts that wrap around the call to the tests. The benefit of having everything through CLI is that developers can easily just filter some of the tests they're currently working on without modifying file (and risking commiting it accidentally). Similar to my previous point, it is something we can change in the future, but depending on the number of adopters, it might be easier or harder.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename --filter option to --exclude-filter

Given we already define filters in the JSON file, I don't know if there's a need for having two cli parameters, or instead could we have just one (--filter) and update the schema so it allows for specifying both inclusion and exclusion - I don't have a strong opinion; just a thought, as I haven't seen them separate in other farameworks.

given the current cli options which allows to specify multiple testsuites,
i thought it's natural to accept multiple filters.

no changes to schema

Not sure if we actually need a nested structure here (testsuite->tests); if we implement regex/glob we could probably just have a list of strings? We can start with this one as it might seem a bit simpler but once we update it, we'll have to update all the consumers as well (not sure how many runtimes will onboard by then though).

i'm not the person who invented the testsuite->tests structure in this repo.
honestly speaking i don't think the testsuite concept makes much sense.

maybe we can use some kind of string match with test id, where test id is:

test_id = testsuite + '/' + test

I'm also not 100% sure about file vs cli parameter. Whereas I see the benefit you mentioned above, I think it doesn't matter that much for runtimes as they'll have their own CI scripts that wrap around the call to the tests. The benefit of having everything through CLI is that developers can easily just filter some of the tests they're currently working on without modifying file (and risking commiting it accidentally). Similar to my previous point, it is something we can change in the future, but depending on the number of adopters, it might be easier or harder.

as a developer, i feel it easier to copy/modify a file than tweaking cli options.
but i can understand you have a different preference.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To unblock the change, let's move on with your suggestion here #35 (comment), we'll adapt it once we have more feedback.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To unblock the change, let's move on with your suggestion here #35 (comment), we'll adapt it once we have more feedback.

done

@yamt yamt force-pushed the skip branch 2 times, most recently from 7afac23 to 10b4115 Compare January 4, 2023 05:05
with open(filename, encoding="utf-8") as file:
self.filter_dict = json.load(file)

def should_skip(self, test_suite_name: str, test_name: str) -> Tuple[bool, Any]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should that be str instead of Any?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i made it Any because it can be None.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case it should be Tuple[bool, Optional[str]]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc such complex types are rejected by tools i was using when writing this code. i guess it's better to avoid being too eager for now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are those tools? I think mypy should be able to handle that. Unless we really except passing here something other than str or None, I'd rather stick to precise types. That also helps understanding the code; in fact, I wasn't sure what is being returned here until I've looked to the implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are those tools? I think mypy should be able to handle that. Unless we really except passing here something other than str or None, I'd rather stick to precise types. That also helps understanding the code; in fact, I wasn't sure what is being returned here until I've looked to the implementation.

i think it was mypy. but i don't remember.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a few static code analyzers as part of CI (including mypy); I'd suggest giving it a try, and if for some reason it fails, we can open an issue for mypy and switch back to Any for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tried more strict annotation and for some reasons it worked today.

maybe the annotation which didn't work was different from this version. i don't remember.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tried more strict annotation and for some reasons it worked today.

maybe the annotation which didn't work was different from this version. i don't remember.

now i remember. the mypy version used by the ci doesn't handle these complex type annotations well. i've updated the requirement.

return TestCase(
name=os.path.splitext(os.path.basename(test_path))[0],
config=config,
result=Result(output=Output(0, "", ""), is_executed=False, failures=[]),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the output be optional? Or rather have an union of output|skip_reason and the value is picked up based on is_executed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe. i'd like to postpone it for later PRs.

it would be nicer to be able to represent "timed out" as well. #42

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, we can refactor that piece as part of #42 then.

Copy link
Collaborator

@loganek loganek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a minor comment regarding tests

As it seems necessary for
"test-runner/wasi_test_runner/filters.py: make type annotation more strict"

```
wasi_test_runner/filters.py:26: error: Incompatible return value type (got "Tuple[bool, None]", expected "Union[Tuple[Literal[True], str], Tuple[Literal[False], None]]")  [return-value]
wasi_test_runner/filters.py:29: error: Incompatible return value type (got "Tuple[bool, Any]", expected "Union[Tuple[Literal[True], str], Tuple[Literal[False], None]]")  [return-value]
wasi_test_runner/filters.py:30: error: Incompatible return value type (got "Tuple[bool, None]", expected "Union[Tuple[Literal[True], str], Tuple[Literal[False], None]]")  [return-value]
```
@yamt
Copy link
Contributor Author

yamt commented Jan 20, 2023

@loganek are you waiting for fixes for your "minor comment"?

@loganek
Copy link
Collaborator

loganek commented Jan 20, 2023

I'm ok with merging that as it is but I'd like to see a bit more tests. Let me know if you can add them, otherwise I'll open an issue and might pick that up later.

@loganek loganek merged commit babca49 into WebAssembly:main Jan 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants