-
Notifications
You must be signed in to change notification settings - Fork 309
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
Add workerd test
for running unit tests under workerd
#341
Conversation
ad11d97
to
075ad9b
Compare
src/workerd/api/blob-test.capnp
Outdated
|
||
const unitTests :Workerd.Config = ( | ||
services = [ | ||
( name = "blob-test", |
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.
do you think we can generate this file in most cases? Would be great to create just 1 file for test rather than two.
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 thought a lot about this. Many tests will need to customize the configuration, e.g. to test bindings, set up actors, or customize compat flags. I don't think we can avoid having some sort of way to specify configuration.
But I agree it would be nice to have the code and config in a single file. This is one of my future TODO points in the PR description.
One idea I've had is to introduce a new block-quote syntax in Cap'n Proto that is convenient for quoting large blocks of text, so that you could the JavaScript conveniently in the capnp file, like:
using Workerd = import "/workerd/workerd.capnp";
const unitTests :Workerd.Config = (
services = [
( name = "blob-test",
worker = (
modules = [
(name = "worker", esModule = .code)
],
compatibilityDate = "2023-01-15",
)
),
],
);
const code :Text = """
// JavaScript code here!
export default {
async test(ctrl, env, ctx) {
// ...
}
}
"""
However, this might have some challenges when it comes to things like syntax highlighting?
Thoughts?
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.
You could solve the syntax highlighting challenges by allowing something like this in capnp:
const code :Text = js"""
// JavaScript code here!
export default {
async test(ctrl, env, ctx) {
// ...
}
}
"""
i.e. lang
prefixes for string literals.
Though I personally don't think having two separate files is a big deal.
// Implements glob filters. Copied from kj/test.{h,c++}, modified only to avoid copying the | ||
// pattern in the constructor. | ||
// | ||
// TODO(cleanup): Should this be a public API in KJ? |
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.
why not simply use <regex>
?
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.
Globs are much easier to read and write than regexes, and I don't think this use case really needs the power of regexes.
80aa2a2
to
379abeb
Compare
Ugh why does GitHub collapse force-pushes so stupidly? Here's the changes I made since everyone reviewed: I also rebased on main. |
Still LGTM |
379abeb
to
b3e4b04
Compare
(rebased on main) |
d3824dc
to
4310378
Compare
This method is overriding a virtual method from a privately-inherited interface (`WorkerInterface`), hence it should be private.
This checks if the service can handle a particular event type. This will be used to check for the presence of test handlers.
The handler is expected to throw an exception on failure. Example: ``` export default { async test(controller, env, ctx) { if (1 + 1 != 2) { throw new Error("math is broken"); } } } ```
We'll want to reuse `startServices()` when running tests, but we don't want to listen on sockets in that case.
blob-test.js is copied directly from our internal test suite, but adapted to use the new `test()` entrypoint. TODO: It's annoying that we need two files for a test. Perhaps the `.capnp` format could be extended with yet another way of writing strings that lets the JavaScript code be embedded in the capnp file in a way that is convenient to read and edit.
Otherwise, when using the Ekam build system, Ekam will automatically try to compile the `.capnp` files using the capnp code generator. This doesn't work for two reasons: 1. Normally `.capnp` files require a file ID. `workerd` configs are unusual in not requiring one. 2. The import path `/workerd/workerd.capnp` doesn't actually exist -- the real path in the code is `/workerd/server/workerd.capnp`.
This is needed to make ASAN builds work. Our internal CI runs all tests under ASAN automatically, including these new wd_test rules.
c19d5c7
to
faaa7cc
Compare
Tests are written by defining an entrypoint with a method
test()
, similar tofetch()
:Next, define a normal workerd configuration with this file as a service.
Then, do:
All exported
test()
handlers will run. The test passes if none of them throw an exception.Check out the sample included in this PR for a bit more detail.
Additionally, this PR adds a
wd_test
Bazel rule and even uses it to bring in one of our (previously-internal) API tests (blob-test).TODO (in future PRs):
fetch()
. Should this be built-in, or a library? Probably a library, where you configure the globalfetch()
to loop back to a separate test entrypoint that implements the mock?