Skip to content

Introduce lit/FileCheck tests#3367

Merged
tlively merged 21 commits into
WebAssembly:masterfrom
tlively:lit-filecheck
Nov 18, 2020
Merged

Introduce lit/FileCheck tests#3367
tlively merged 21 commits into
WebAssembly:masterfrom
tlively:lit-filecheck

Conversation

@tlively

@tlively tlively commented Nov 15, 2020

Copy link
Copy Markdown
Member

lit and FileCheck are the tools used to run the majority of tests in LLVM. Each
lit test file contains the commands to be run for that test, so lit tests are
much more flexible and can be more precise than our current ad hoc testing
system. FileCheck reads expected test output from comments, so it allows test
output to be written alongside and interspersed with test input, making tests
more readable and precise than in our current system.

This PR adds a new suite to check.py that runs lit tests in the test/lit
directory. A few tests have been ported to demonstrate the features of the new
test runner.

This change is motivated by a need for greater flexibility in testing wasm-split.
See #3359.

@tlively

tlively commented Nov 15, 2020

Copy link
Copy Markdown
Member Author

@kripken @aheejin @dschuff @MaxGraey What would you think about this direction? I would rather use lit + FileCheck for wasm-split (#3359) and invest time in porting the other tests to lit + FileCheck than invest time in writing a new ad hoc test script for wasm-split.

@tlively

tlively commented Nov 15, 2020

Copy link
Copy Markdown
Member Author

@sbc100 why a new check.py option was necessary in #3359, but I will answer here to keep the respective discussions more focused.

Most users will never have to use this option, even if they do out-of-tree builds, since it is only necessary when --binaryen-bin is set to the install directory rather than the build directory. The way it is currently written, CMake emits a lit configuration file that tells lit where to find the built binaries and where to find the tests. It would be possible to have this configuration file point to the binaries in the install directory rather than the build directory, but check.py would still have to know how to find the lit configuration file itself. Between the options of installing the lit configuration to the install directory and adding a new check.py option to cover this corner case, adding the option seemed better.

@tlively tlively mentioned this pull request Nov 15, 2020
@kripken

kripken commented Nov 15, 2020

Copy link
Copy Markdown
Member

Personally this sounds fine to me. I'm not worried about having multiple test frameworks, as long as they are all very simple and they all are useful in their own right. (I'd feel very differently about non-test code!)

My main concern about lit is how easy will it be to update test expectations - can we get ./auto_update_tests to do everything automatically like it does now even for those tests? Sounds from the above like that's the plan. But it would require "clever" diffing it seems?

My small concern about lit is that while it's nice to see the input and output in the same file, the output is in a comment. That's less readable and also it's not directly runnable. For example, right now you can run an input wast through a tool, then run the output wast through the same, and compare results. With lit you'd need to construct the output wast somehow from those comments..? If we don't have a great solution for that, I'd still be fine with using lit for some tests where running the output is not that important - but it would make me skeptical of the benefit of porting existing tests to lit (but leaving them as is sounds fine to me anyhow as I said earlier).

@tlively

tlively commented Nov 15, 2020

Copy link
Copy Markdown
Member Author

My main concern about lit is how easy will it be to update test expectations - can we get ./auto_update_tests to do everything automatically like it does now even for those tests? Sounds from the above like that's the plan. But it would require "clever" diffing it seems?

Yes, the auto update scripts would be more complex for lit tests. But LLVM has such scripts, so at the very least we could use those as a starting point.

My small concern about lit is that while it's nice to see the input and output in the same file, the output is in a comment. That's less readable and also it's not directly runnable. For example, right now you can run an input wast through a tool, then run the output wast through the same, and compare results. With lit you'd need to construct the output wast somehow from those comments..? If we don't have a great solution for that, I'd still be fine with using lit for some tests where running the output is not that important - but it would make me skeptical of the benefit of porting existing tests to lit (but leaving them as is sounds fine to me anyhow as I said earlier).

It should be trivial to construct the output by running the commands in the ;; RUN: lines of the tests. Also, when a test fails, lit will print out the exact commands to run to reproduce the failure yourself, so I expect that reproducing output will be at least as easy with lit tests as with current tests.

I still think that porting existing tests to lit will be a huge win once we have auto update scripts for lit tests, but if you're ok with adding lit as a new test runner, we can use it for wasm-split for now and defer the decision on whether to automatically port other tests until we have a more concrete idea of how good the results would be.

@sbc100

sbc100 commented Nov 16, 2020

Copy link
Copy Markdown
Member

@sbc100 why a new check.py option was necessary in #3359, but I will answer here to keep the respective discussions more focused.

Most users will never have to use this option, even if they do out-of-tree builds, since it is only necessary when --binaryen-bin is set to the install directory rather than the build directory. The way it is currently written, CMake emits a lit configuration file that tells lit where to find the built binaries and where to find the tests. It would be possible to have this configuration file point to the binaries in the install directory rather than the build directory, but check.py would still have to know how to find the lit configuration file itself. Between the options of installing the lit configuration to the install directory and adding a new check.py option to cover this corner case, adding the option seemed better.

Can we simplify things my mandating that tests can only run against a build directory and never against an install directory?

@sbc100 sbc100 closed this Nov 16, 2020
@sbc100 sbc100 reopened this Nov 16, 2020
@sbc100

sbc100 commented Nov 16, 2020

Copy link
Copy Markdown
Member

My main concern about lit is how easy will it be to update test expectations - can we get ./auto_update_tests to do everything automatically like it does now even for those tests? Sounds from the above like that's the plan. But it would require "clever" diffing it seems?

Yes, the auto update scripts would be more complex for lit tests. But LLVM has such scripts, so at the very least we could use those as a starting point.

I think we if we make this transition we can/should do it incrementally.

If there are certainly test suites for which it makes sense to stick with the "expected output is this entire" file approach I think that is perfectly reasonable. I think its fine for there to exist two catagories of tests:

  1. Check just specific lines, and do so via inline comments.
  2. Check entire output and do so using a separate file.

Trying to make all tests fit into (1) doesn't make sense to me (at least not yet). But I can't see that for many tests it is clearly a better option.

I am not particularly excited about having arbitrarily complex scripts that try to make the auto-update system work with (1). I might make sense for certain tests and not others.

My small concern about lit is that while it's nice to see the input and output in the same file, the output is in a comment. That's less readable and also it's not directly runnable. For example, right now you can run an input wast through a tool, then run the output wast through the same, and compare results. With lit you'd need to construct the output wast somehow from those comments..? If we don't have a great solution for that, I'd still be fine with using lit for some tests where running the output is not that important - but it would make me skeptical of the benefit of porting existing tests to lit (but leaving them as is sounds fine to me anyhow as I said earlier).

It should be trivial to construct the output by running the commands in the ;; RUN: lines of the tests. Also, when a test fails, lit will print out the exact commands to run to reproduce the failure yourself, so I expect that reproducing output will be at least as easy with lit tests as with current tests.

I still think that porting existing tests to lit will be a huge win once we have auto update scripts for lit tests, but if you're ok with adding lit as a new test runner, we can use it for wasm-split for now and defer the decision on whether to automatically port other tests until we have a more concrete idea of how good the results would be.

I think we should do this incrementally, that way we can be exposed different pain points of the two systems side by side side.

My feeling is that biggest issue with the current system is the lack of ability to run individual tests, or even know how to re-run a given test when something fails.. or even tell from the output which test exactly failed.. mostly because tests do not have unique names or IDs. While lit + FileCheck conversion could solve that issue, it could also be solved in other ways. For example, Wouter's --filter option helps in this direction.

@tlively

tlively commented Nov 16, 2020

Copy link
Copy Markdown
Member Author

@aheejin, a brief investigation in #3375 shows that the clang package we are already bringing in for the lint builder does not include llvm-lit or FileCheck. We also don't install that package on Mac or Windows, so I think for now the best thing to do is to continue using the python packages since we already know they can be installed and are portable.

@sbc100

sbc100 commented Nov 16, 2020

Copy link
Copy Markdown
Member

@aheejin, a brief investigation in #3375 shows that the clang package we are already bringing in for the lint builder does not include llvm-lit or FileCheck. We also don't install that package on Mac or Windows, so I think for now the best thing to do is to continue using the python packages since we already know they can be installed and are portable.

BTW we should probably use requirements-dev.txt like we do in emscripten to capture these dependencies.

@tlively

tlively commented Nov 17, 2020

Copy link
Copy Markdown
Member Author

@sbc100 sounds good, but let's put that in a separate PR that also adds flake8 to that file.

@sbc100

sbc100 commented Nov 17, 2020

Copy link
Copy Markdown
Member

Unless you are in a hurry I suggest we move flake8 to that file first.. thus avoiding the need to change the CI script at all for this change.

@tlively

tlively commented Nov 17, 2020

Copy link
Copy Markdown
Member Author

Oh, does github actions know about that file or something?

@sbc100

sbc100 commented Nov 17, 2020

Copy link
Copy Markdown
Member

No we just do pip3 install -r requirements-dev.txt

tlively added a commit to tlively/binaryen that referenced this pull request Nov 17, 2020
This file makes it simple for users and CI bots to install all the Python dev
dependencies necessary to run the test suite. Right now it only contains flake8,
but soon it will contain lit and filecheck as well (see WebAssembly#3367).
tlively added a commit that referenced this pull request Nov 17, 2020
This file makes it simple for users and CI bots to install all the Python dev
dependencies necessary to run the test suite. Right now it only contains flake8,
but soon it will contain lit and filecheck as well (see #3367).
lit and FileCheck are the tools used to run the majority of tests in LLVM. Each
lit test file contains the commands to be run for that test, so lit tests are
much more flexible and can be more precise than our current ad hoc testing
system. FileCheck reads expected test output from comments, so it allows test
output to be written alongside and interspersed with test input, making tests
much more readable than in our current system.

This PR adds a new suite to check.py that runs lit tests in the test/lit
directory. The only such test so far contains a few test cases ported from the
optimize-instructions_all-features test, meant to demonstrate what our tests
would look like if they were ported to lit and FileCheck.

To avoid adding yet another testing framework (https://xkcd.com/927/), I would
like to try to port our existing tests to use lit and FileCheck. This should be
done at least partially automatically by scripts that will remain useful in the
future for updating test expectations.
@tlively tlively changed the title [Discussion] lit/FileCheck tests Introduce lit/FileCheck tests Nov 17, 2020
@tlively tlively marked this pull request as ready for review November 17, 2020 07:27

@sbc100 sbc100 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is looking very nice indeed!

Comment thread .gitignore Outdated
*.o
*.obj
compile_commands.json
**/Output

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just /Output should be enough, no?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, lit actually sprinkles Output directories all over the place. After running the tests in this PR locally with an in-tree build I have

./test/Output
./test/validation/Output
./test/wasm-emscripten-finalize/Output

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Cluttering test directory does not sound very ideal.. Can we put all of them under out/ or somewhere? There seems to be an option called test_exec_root in llvm-lit with which we can control the output directory. Can we use it?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These files get written to the build directory, so it only clutters your source tree if your do "in-tree" building.. which I think most of us dont.

If you do do "in-tree" building your source tree is already full of clutter.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we banned in-tree building we could remove all these things from gitignore.. which I would personally be an favor of. I personally like it when git status tells me about stray .o files in my checkout, but these rules prevent that.

Comment thread .gitignore Outdated
*.obj
compile_commands.json
**/Output
**/lit.site.cfg.py

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are these files created during the build? Where are they created exactly?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This file is generated at build configuration time by CMake. For a normal in-tree build, this is created at ./test/lit/lit.site.cfg.py, but it's relative to the CMake build directory rather than the source directory.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Got it. In that case it should just be /test/lit/lit.site.cfg.py since it has a fixed location.

Comment thread .flake8
E241, # space after comma (ignored for list in gen-s-parser.py)
W504 # line break after binary operator
exclude = ./test/emscripten,./test/spec,./test/wasm-install
exclude = ./test/emscripten,./test/spec,./test/wasm-install,./test/lit

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

flake8 complains about config being used before it is defined in the lit config and similar non-problems.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How about test/lib/*config.py or something like that then? Or will this directory be otherwise free of python code so it doesn't matter?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, this directory will otherwise be free of Python code.

Comment thread scripts/lit_wrapper.py
@@ -0,0 +1,20 @@
# Copyright 2020 WebAssembly Community Group participants

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

#! python3?

@tlively tlively requested review from kripken and sbc100 November 17, 2020 20:28

@aheejin aheejin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It looks very nice! As I said, I'm not sure whether migrating all existing tests is feasible or better; there are cases we change some parts of existing passes that affect many existing tests and running ./auto_update_tests.py can often show what its effects would be like on many parts on them, which I found rather convenient. But having this as an alternative testing framework looks fine.

Comment thread .gitignore Outdated
*.o
*.obj
compile_commands.json
**/Output

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Cluttering test directory does not sound very ideal.. Can we put all of them under out/ or somewhere? There seems to be an option called test_exec_root in llvm-lit with which we can control the output directory. Can we use it?

Comment thread requirements-dev.txt

flake8==3.7.8
filecheck==0.0.17
lit==0.11.0.post1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not familiar with Python ports of filecheck and lit... So lit needs a wrapper script but filecheck can run as is like a normal executable?

@kripken kripken left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No update to ./auto_update_test.py for lit tests? 😜

@tlively

tlively commented Nov 18, 2020

Copy link
Copy Markdown
Member Author

No update to ./auto_update_test.py for lit tests? 😜

Not for these hand-written ones :P

@tlively

tlively commented Nov 18, 2020

Copy link
Copy Markdown
Member Author

@aheejin, nice find with the test_exec_root. You were right that I could move the Output directories into out/test/ with that.

@tlively tlively merged commit 1e527ec into WebAssembly:master Nov 18, 2020
@tlively tlively deleted the lit-filecheck branch November 18, 2020 19:27
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.

4 participants