-
Notifications
You must be signed in to change notification settings - Fork 310
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #341 from cloudflare/kenton/test-entrypoint
Add `workerd test` for running unit tests under workerd
- Loading branch information
Showing
18 changed files
with
852 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
def wd_test( | ||
src, | ||
data = [], | ||
name = None, | ||
args = [], | ||
**kwargs): | ||
"""Rule to define tests that run `workerd test` with a particular config. | ||
Args: | ||
src: A .capnp config file defining the test. (`name` will be derived from this if not | ||
specified.) The extension `.wd-test` is also permitted instead of `.capnp`, in order to | ||
avoid confusing other build systems that may assume a `.capnp` file should be complied. | ||
data: Files which the .capnp config file may embed. Typically JavaScript files. | ||
args: Additional arguments to pass to `workerd`. Typically used to pass `--experimental`. | ||
""" | ||
|
||
# Add workerd binary to "data" dependencies. | ||
data = data + [src, "//src/workerd/server:workerd"] | ||
|
||
# Add initial arguments for `workerd test` command. | ||
args = [ | ||
"$(location //src/workerd/server:workerd)", | ||
"test", | ||
"$(location {})".format(src), | ||
] + args | ||
|
||
# Default name based on src. | ||
if name == None: | ||
name = src.removesuffix(".capnp").removesuffix(".wd-test") | ||
|
||
_wd_test( | ||
name = name, | ||
data = data, | ||
args = args, | ||
**kwargs | ||
) | ||
|
||
def _wd_test_impl(ctx): | ||
# Bazel insists that the rule must actually create the executable that it intends to run; it | ||
# can't just specify some other executable with some args. OK, fine, we'll use a script that | ||
# just execs its args. | ||
ctx.actions.write( | ||
output = ctx.outputs.executable, | ||
content = "#! /bin/sh\nexec \"$@\"\n", | ||
is_executable = True, | ||
) | ||
|
||
return [ | ||
DefaultInfo( | ||
executable = ctx.outputs.executable, | ||
runfiles = ctx.runfiles(files = ctx.files.data) | ||
), | ||
] | ||
|
||
_wd_test = rule( | ||
implementation = _wd_test_impl, | ||
test = True, | ||
attrs = { | ||
"workerd": attr.label( | ||
allow_single_file = True, | ||
executable = True, | ||
cfg = "exec", | ||
default = "//src/workerd/server:workerd", | ||
), | ||
"flags": attr.string_list(), | ||
"data": attr.label_list(allow_files = True), | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# This is an example configuration for running unit tests. | ||
# | ||
# (If you're not already familiar with the basic config format, check out the hello world example | ||
# first.) | ||
# | ||
# Most projects will probably use some sort of script or tooling to auto-generate this | ||
# configuration (such as Wrangler), and instead focus on the contents of the JavaScript file. | ||
# | ||
# To run the tests, do: | ||
# | ||
# workerd test config.capnp | ||
|
||
using Workerd = import "/workerd/workerd.capnp"; | ||
|
||
const unitTests :Workerd.Config = ( | ||
services = [ | ||
# Define the service to be tested. | ||
(name = "main", worker = .testWorker), | ||
|
||
# Not required, but we can redefine the special "internet" service so that it disallows any | ||
# outgoing connections. This prohibits the test from talking to the network. | ||
(name = "internet", network = (allow = [])) | ||
], | ||
|
||
# For running tests, we do not need to define any sockets, since tests do not accept incoming | ||
# connections. | ||
); | ||
|
||
const testWorker :Workerd.Worker = ( | ||
# Just a regular old worker definition. | ||
modules = [ | ||
(name = "worker", esModule = embed "worker.js") | ||
], | ||
compatibilityDate = "2023-01-15", | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Exporting a test is like exporting a `fetch()` handler. | ||
// | ||
// It's common to want to write multiple tests in one file. We can export each | ||
// test under a different name. (BTW you can also export multiple `fetch()` | ||
// handlers this way! But that's less commonly-used.) | ||
|
||
export let testStrings = { | ||
async test(ctrl, env, ctx) { | ||
if ("foo" + "bar" != "foobar") { | ||
throw new Error("strings are broken!"); | ||
} | ||
} | ||
}; | ||
|
||
export let testMath = { | ||
async test(ctrl, env, ctx) { | ||
if (1 + 1 != 2) { | ||
throw new Error("math is broken!"); | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
function assertEqual(a, b) { | ||
if (a !== b) { | ||
throw new Error(a + " !== " + b); | ||
} | ||
} | ||
|
||
export default { | ||
async test(ctrl, env, ctx) { | ||
let blob = new Blob(["foo", new TextEncoder().encode("bar"), "baz"]); | ||
assertEqual(await blob.text(), "foobarbaz"); | ||
assertEqual(new TextDecoder().decode(await blob.arrayBuffer()), "foobarbaz"); | ||
assertEqual(blob.type, ""); | ||
|
||
let blob2 = new Blob(["xx", blob, "yy", blob], {type: "application/whatever"}); | ||
assertEqual(await blob2.text(), "xxfoobarbazyyfoobarbaz"); | ||
assertEqual(blob2.type, "application/whatever"); | ||
|
||
let blob3 = new Blob(); | ||
assertEqual(await blob3.text(), ""); | ||
|
||
let slice = blob2.slice(5, 16); | ||
assertEqual(await slice.text(), "barbazyyfoo"); | ||
assertEqual(slice.type, ""); | ||
|
||
let slice2 = slice.slice(-5, 1234, "type/type"); | ||
assertEqual(await slice2.text(), "yyfoo"); | ||
assertEqual(slice2.type, "type/type"); | ||
|
||
assertEqual(await blob2.slice(5).text(), "barbazyyfoobarbaz"); | ||
assertEqual(await blob2.slice().text(), "xxfoobarbazyyfoobarbaz"); | ||
assertEqual(await blob2.slice(3, 1).text(), ""); | ||
|
||
{ | ||
let stream = blob.stream(); | ||
let reader = stream.getReader(); | ||
let readResult = await reader.read(); | ||
assertEqual(readResult.done, false); | ||
assertEqual(new TextDecoder().decode(readResult.value), "foobarbaz"); | ||
readResult = await reader.read(); | ||
assertEqual(readResult.value, undefined); | ||
assertEqual(readResult.done, true); | ||
reader.releaseLock(); | ||
} | ||
|
||
let before = Date.now(); | ||
|
||
let file = new File([blob, "qux"], "filename.txt"); | ||
assertEqual(file instanceof Blob, true); | ||
assertEqual(await file.text(), "foobarbazqux"); | ||
assertEqual(file.name, "filename.txt"); | ||
assertEqual(file.type, ""); | ||
if (file.lastModified < before || file.lastModified > Date.now()) { | ||
throw new Error("incorrect lastModified"); | ||
} | ||
|
||
let file2 = new File(["corge", file], "file2", {type: "text/foo", lastModified: 123}); | ||
assertEqual(await file2.text(), "corgefoobarbazqux"); | ||
assertEqual(file2.name, "file2"); | ||
assertEqual(file2.type, "text/foo"); | ||
assertEqual(file2.lastModified, 123); | ||
|
||
try { | ||
new Blob(["foo"], {endings: "native"}); | ||
throw new Error("use of 'endings' should throw"); | ||
} catch (err) { | ||
if (!err.message.includes("The 'endings' field on 'Options' is not implemented.")) { | ||
throw err; | ||
} | ||
} | ||
|
||
// Test type normalization. | ||
assertEqual(new Blob([], {type: "FoO/bAr"}).type, "foo/bar"); | ||
assertEqual(new Blob([], {type: "FoO\u0019/bAr"}).type, ""); | ||
assertEqual(new Blob([], {type: "FoO\u0020/bAr"}).type, "foo /bar"); | ||
assertEqual(new Blob([], {type: "FoO\u007e/bAr"}).type, "foo\u007e/bar"); | ||
assertEqual(new Blob([], {type: "FoO\u0080/bAr"}).type, ""); | ||
assertEqual(new File([], "foo.txt", {type: "FoO/bAr"}).type, "foo/bar"); | ||
assertEqual(blob2.slice(1, 2, "FoO/bAr").type, "foo/bar"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using Workerd = import "/workerd/workerd.capnp"; | ||
|
||
const unitTests :Workerd.Config = ( | ||
services = [ | ||
( name = "blob-test", | ||
worker = ( | ||
modules = [ | ||
(name = "worker", esModule = embed "blob-test.js") | ||
], | ||
compatibilityDate = "2023-01-15", | ||
) | ||
), | ||
], | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.