-
Notifications
You must be signed in to change notification settings - Fork 4
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
Automated regression testing for prism work #26
Conversation
2c7c2e1
to
d6f5382
Compare
1. Add a new test suite that only tests files in the `test/prism_regression` folder 2. Modify Sorbet's test code to allow the user to specify a parser 3. Add logic to the pipeline test runner to call `runPrismParser` when specified
96b6ab5
to
1a72721
Compare
@@ -272,6 +281,11 @@ test_suite( | |||
tests = ["whitequark_parser_corpus"], | |||
) | |||
|
|||
test_suite( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds a new test suite to bazel, allowing us to run ./bazel test //test:prism
as a shorthand for all of the prism regression tests, which are defined above.
@@ -262,6 +262,15 @@ pipeline_tests( | |||
extra_files = ["testdata/lsp/rubyfmt-stub/rubyfmt"], | |||
) | |||
|
|||
pipeline_tests( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tells bazel which tests to run, which runner to use, and which options to pass into the tests (in this case, parser = "prism"
, which is a new option that I implemented).
@@ -112,7 +114,7 @@ _TEST_RUNNERS = { | |||
"PackagerTests": ":pipeline_test_runner", | |||
} | |||
|
|||
def pipeline_tests(suite_name, all_paths, test_name_prefix, extra_files = [], tags = []): | |||
def pipeline_tests(suite_name, all_paths, test_name_prefix, extra_files = [], tags = [], parser = "sorbet"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes in this file us to specify which parser to use for tests and then pass that value along to the test runner.
@@ -855,6 +860,9 @@ int main(int argc, char *argv[]) { | |||
cxxopts::Options options("test_corpus", "Test corpus for Sorbet typechecker"); | |||
options.allow_unrecognised_options().add_options()("single_test", "run over single test.", | |||
cxxopts::value<std::string>()->default_value(""), "testpath"); | |||
options.allow_unrecognised_options().add_options()("parser", "The parser to use while testing.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is where the test runner allows us to pass in a prism option and then pulls the value from the provided options.
@@ -1,4 +1,5 @@ | |||
GENERATED_SRCS = [ | |||
"src/diagnostic.c", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how I missed this and how Sorbet has been building locally without it 🤔 But CI was having trouble and I realized I'd forgotten a file!
@@ -350,8 +350,7 @@ const unique_ptr<parser::Node> convertPrismToSorbet(pm_node_t *node, pm_parser_t | |||
} | |||
} | |||
|
|||
unique_ptr<parser::Node> runPrismParser(core::GlobalState &gs, core::FileRef file, const options::Printers &print, | |||
bool traceLexer, bool traceParser) { | |||
unique_ptr<parser::Node> runPrismParser(core::GlobalState &gs, core::FileRef file) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplified the method signature to remove things I'm not using (yet) for easy use in tests.
@@ -24,6 +25,7 @@ std::vector<core::FileRef> reserveFiles(std::unique_ptr<core::GlobalState> &gs, | |||
std::vector<ast::ParsedFile> index(core::GlobalState &gs, absl::Span<core::FileRef> files, const options::Options &opts, | |||
WorkerPool &workers, const std::unique_ptr<const OwnedKeyValueStore> &kvstore); | |||
|
|||
std::unique_ptr<parser::Node> runPrismParser(core::GlobalState &gs, core::FileRef file); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to the public API for use in tests. I will eventually move this into its own namespace so please don't worry about it for now 😁
if (parser == realmain::options::Parser::SORBET) { | ||
std::cout << "Parsing with sorbet" << std::endl; | ||
core::UnfreezeNameTable nameTableAccess(*gs); // enters original strings | ||
|
||
auto settings = parser::Parser::Settings{}; | ||
nodes = parser::Parser::run(*gs, file, settings); | ||
} else if (parser == realmain::options::Parser::PRISM) { | ||
std::cout << "Parsing with prism" << std::endl; | ||
nodes = realmain::pipeline::runPrismParser(*gs, file); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here's where we actually use the parser option to decide which parser to use. Sorbet's test implementation is weird, in that it breaks down all the components of the pipeline and tests them separately in order to inject special testing logic between them. Hence, why I had to call runPrismParser
here. As I've said, I will eventually move that method into its own namespace, which will make it easier to reuse without dipping into pipeline internals.
core::UnfreezeNameTable nameTableAccess(*gs); // enters original strings | ||
|
||
auto settings = parser::Parser::Settings{}; | ||
nodes = parser::Parser::run(*gs, file, settings); | ||
} else if (parser == realmain::options::Parser::PRISM) { | ||
std::cout << "Parsing with prism" << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to leave these print statements because without some confirmation that we're hitting this code path, there (afaik) no way to tell that we are actually parsing with prism rather than the sorbet parser 😆
with: | ||
ruby-version: 3.3.0 | ||
- name: Run tests | ||
run: ./bazel test //test:prism --config=dbg --define RUBY_PATH='/opt/hostedtoolcache/Ruby/3.3.0/x64' --test_output=all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passes in the path to the Ruby version installed by GitHub actions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like building takes 20 minutes. It might be worth exploring if we can use something simple like https://github.com/bazel-contrib/setup-bazel and get caching out of the box.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent idea - https://github.com/Shopify/team-ruby-dx/issues/1187
@@ -0,0 +1,3 @@ | |||
# typed: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you can add some *.parse-tree.exp
files to ensure the produced AST is correct?
Like what's done with https://github.com/sorbet/sorbet/blob/master/test/testdata/parser/kwnil.parse-tree.exp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! I'll look into this now.
with: | ||
ruby-version: 3.3.0 | ||
- name: Run tests | ||
run: ./bazel test //test:prism --config=dbg --define RUBY_PATH='/opt/hostedtoolcache/Ruby/3.3.0/x64' --test_output=all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like building takes 20 minutes. It might be worth exploring if we can use something simple like https://github.com/bazel-contrib/setup-bazel and get caching out of the box.
1a72721
to
7f98a17
Compare
@@ -0,0 +1,3 @@ | |||
Integer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Morriar here are my .parse-tree.exp
tests :)
7f98a17
to
301744c
Compare
Best read commit-by-commit!
Motivation
As we work on parsing with Prism in Sorbet, we should do some automated testing to ensure that we don't introduce any regressions or break our previous work. However, until we have Prism parsing most kinds of nodes, it doesn't make any sense to run the whole Sorbet test suite, since most tests will just fail.
This PR introduces a new test suite, called
prism_test_corpus
, that only runs tests in thetest/prism_regression
folder. We can add tests to this folder as we implement prism parsing for each node, and then eventually turn on other portions of the Sorbet test suite as we get closer to completion.Test plan
You can see the automatic tests in the check in this PR 🥳
You can run the tests locally with the following command: