2
2
# Licensed under the Apache 2.0 license found in the LICENSE file or at:
3
3
# https://opensource.org/licenses/Apache-2.0
4
4
5
- # The public entry point is a macro named wpt_test. It first invokes a private
6
- # rule named _wpt_test_gen to access the files in the wpt filegroup and
7
- # generate a corresponding wd-test file. It then invokes the wd_test macro
8
- # to set up the test.
9
-
10
5
load ("//:build/wd_test.bzl" , "wd_test" )
11
6
12
- def wpt_test (name , wpt_directory , test_js ):
13
- test_gen_rule = "{}@_wpt_test_gen" .format (name )
14
- _wpt_test_gen (
15
- name = test_gen_rule ,
7
+ def wpt_test (name , wpt_directory , test_config ):
8
+ """
9
+ Main entry point.
10
+ 1. Generates a workerd test suite in JS. This contains the logic to run
11
+ each WPT test file, applying the relevant test config.
12
+ 2. Generates a wd-test file for this test suite. This contains all of the
13
+ paths to modules needed to run the test: generated test suite, test config
14
+ file, WPT test scripts, associated JSON resources.
15
+ """
16
+
17
+ js_test_gen_rule = "{}@_wpt_js_test_gen" .format (name )
18
+ test_config_as_js = test_config .removesuffix (".ts" ) + ".js"
19
+
20
+ _wpt_js_test_gen (
21
+ name = js_test_gen_rule ,
16
22
test_name = name ,
17
23
wpt_directory = wpt_directory ,
18
- test_js = test_js ,
24
+ test_config = test_config_as_js ,
25
+ )
26
+
27
+ wd_test_gen_rule = "{}@_wpt_wd_test_gen" .format (name )
28
+ _wpt_wd_test_gen (
29
+ name = wd_test_gen_rule ,
30
+ test_name = name ,
31
+ wpt_directory = wpt_directory ,
32
+ test_config = test_config_as_js ,
33
+ test_js_generated = js_test_gen_rule ,
19
34
)
20
35
21
36
wd_test (
22
37
name = "{}" .format (name ),
23
- src = test_gen_rule ,
38
+ src = wd_test_gen_rule ,
24
39
args = ["--experimental" ],
40
+ ts_deps = ["//src/wpt:wpt-test-harness" ],
25
41
data = [
26
42
"//src/wpt:wpt-test-harness" ,
27
- test_js ,
43
+ test_config ,
44
+ js_test_gen_rule ,
28
45
wpt_directory ,
29
46
"//src/workerd/io:trimmed-supported-compatibility-date.txt" ,
30
47
],
31
48
)
32
49
33
- def _wpt_test_gen_impl (ctx ):
50
+ def _wpt_js_test_gen_impl (ctx ):
51
+ """
52
+ Generates a workerd test suite in JS. This contains the logic to run
53
+ each WPT test file, applying the relevant test config.
54
+ """
55
+
56
+ src = ctx .actions .declare_file ("{}-test.generated.js" .format (ctx .attr .test_name ))
57
+ ctx .actions .write (
58
+ output = src ,
59
+ content = WPT_JS_TEST_TEMPLATE .format (
60
+ test_config = ctx .file .test_config .basename ,
61
+ cases = generate_external_cases (ctx .attr .wpt_directory .files ),
62
+ ),
63
+ )
64
+
65
+ return DefaultInfo (
66
+ files = depset ([src ]),
67
+ )
68
+
69
+ def generate_external_cases (files ):
70
+ """
71
+ Generate a workerd test case that runs each test file in the WPT module.
72
+ """
73
+
74
+ result = []
75
+
76
+ for file in files .to_list ():
77
+ if file .extension == "js" :
78
+ entry = """export const {} = run(config, '{}');""" .format (test_case_name (file .basename ), file .basename )
79
+ result .append (entry )
80
+
81
+ return "\n " .join (result )
82
+
83
+ def test_case_name (filename ):
84
+ """
85
+ Converts a JS filename to a valid JS identifier for use as a test case name.
86
+ WPT files are named with the convention some-words-with-hyphens.some-suffix.js.
87
+ We would turn this into someWordsWithHyphensSomeSuffix.
88
+ """
89
+
90
+ words = (filename
91
+ .removesuffix (".js" )
92
+ .removesuffix (".any" )
93
+ .replace ("." , "-" )
94
+ .split ("-" ))
95
+
96
+ return words [0 ] + "" .join ([word .capitalize () for word in words [1 :]])
97
+
98
+ WPT_JS_TEST_TEMPLATE = """// This file is autogenerated by wpt_test.bzl
99
+ // DO NOT EDIT.
100
+ import {{ run }} from 'wpt:harness';
101
+ import config from '{test_config}';
102
+
103
+ {cases}
104
+ """
105
+
106
+ def _wpt_wd_test_gen_impl (ctx ):
107
+ """
108
+ Generates a wd-test file for this test suite. This contains all of the
109
+ paths to modules needed to run the test: generated test suite, test config
110
+ file, WPT test scripts, associated JSON resources.
111
+ """
112
+
34
113
src = ctx .actions .declare_file ("{}.wd-test" .format (ctx .attr .test_name ))
35
114
ctx .actions .write (
36
115
output = src ,
37
- content = WPT_TEST_TEMPLATE .format (
116
+ content = WPT_WD_TEST_TEMPLATE .format (
38
117
test_name = ctx .attr .test_name ,
39
- test_js = wd_relative_path (ctx .file .test_js ),
118
+ test_config = ctx .file .test_config .basename ,
119
+ test_js_generated = wd_relative_path (ctx .file .test_js_generated ),
40
120
modules = generate_external_modules (ctx .attr .wpt_directory .files ),
41
121
),
42
122
)
@@ -45,14 +125,15 @@ def _wpt_test_gen_impl(ctx):
45
125
files = depset ([src ]),
46
126
)
47
127
48
- WPT_TEST_TEMPLATE = """
128
+ WPT_WD_TEST_TEMPLATE = """
49
129
using Workerd = import "/workerd/workerd.capnp";
50
130
const unitTests :Workerd.Config = (
51
131
services = [
52
132
( name = "{test_name}",
53
133
worker = (
54
134
modules = [
55
- (name = "worker", esModule = embed "{test_js}"),
135
+ (name = "worker", esModule = embed "{test_js_generated}"),
136
+ (name = "{test_config}", esModule = embed "{test_config}"),
56
137
(name = "wpt:harness", esModule = embed "../../../../../workerd/src/wpt/harness.js"),
57
138
{modules}
58
139
],
@@ -75,6 +156,7 @@ def wd_relative_path(file):
75
156
Returns a relative path which can be referenced in the .wd-test file.
76
157
This is four directories up from the bazel short_path
77
158
"""
159
+
78
160
return "../" * 4 + file .short_path
79
161
80
162
def generate_external_modules (files ):
@@ -85,6 +167,7 @@ def generate_external_modules(files):
85
167
Example for a JSON file:
86
168
(name = "resources/urltestdata.json", json = embed "../../../../../wpt/url/resources/urltestdata.json"),
87
169
"""
170
+
88
171
result = []
89
172
90
173
for file in files .to_list ():
@@ -102,14 +185,28 @@ def generate_external_modules(files):
102
185
103
186
return ",\n " .join (result )
104
187
105
- _wpt_test_gen = rule (
106
- implementation = _wpt_test_gen_impl ,
188
+ _wpt_wd_test_gen = rule (
189
+ implementation = _wpt_wd_test_gen_impl ,
190
+ attrs = {
191
+ # A string to use as the test name. Used in the wd-test filename and the worker's name
192
+ "test_name" : attr .string (),
193
+ # A file group representing a directory of wpt tests. All files in the group will be embedded.
194
+ "wpt_directory" : attr .label (),
195
+ # A JS file containing the test configuration.
196
+ "test_config" : attr .label (allow_single_file = True ),
197
+ # An auto-generated JS file containing the test logic.
198
+ "test_js_generated" : attr .label (allow_single_file = True ),
199
+ },
200
+ )
201
+
202
+ _wpt_js_test_gen = rule (
203
+ implementation = _wpt_js_test_gen_impl ,
107
204
attrs = {
108
205
# A string to use as the test name. Used in the wd-test filename and the worker's name
109
206
"test_name" : attr .string (),
110
207
# A file group representing a directory of wpt tests. All files in the group will be embedded.
111
208
"wpt_directory" : attr .label (),
112
- # A JS file containing the actual test logic .
113
- "test_js " : attr .label (allow_single_file = True ),
209
+ # A JS file containing the test configuration .
210
+ "test_config " : attr .label (allow_single_file = True ),
114
211
},
115
212
)
0 commit comments