Changeset 263621 in webkit
- Timestamp:
- Jun 27, 2020 9:08:59 AM (4 years ago)
- Location:
- trunk/LayoutTests/imported/w3c
- Files:
-
- 7 added
- 32 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/imported/w3c/ChangeLog
r263613 r263621 1 2020-06-27 Chris Dumez <cdumez@apple.com> 2 3 Update web-platform-tests/common from upstream 4 https://bugs.webkit.org/show_bug.cgi?id=213665 5 6 Reviewed by Sam Weinig. 7 8 Update web-platform-tests/common from upstream b076c305a256e7fb7. 9 10 * web-platform-tests/common/*: Updated. 11 1 12 2020-06-26 Chris Dumez <cdumez@apple.com> 2 13 -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/META.yml
r245004 r263621 2 2 - zqzhang 3 3 - deniak 4 - gsnedders -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/arrays.js
r232903 r263621 1 // Returns true if the given arrays are equal. Optionally can pass an equality function. 1 /** 2 * Callback for checking equality of c and d. 3 * 4 * @callback equalityCallback 5 * @param {*} c 6 * @param {*} d 7 * @returns {boolean} 8 */ 9 10 /** 11 * Returns true if the given arrays are equal. Optionally can pass an equality function. 12 * @param {Array} a 13 * @param {Array} b 14 * @param {equalityCallback} callbackFunction - defaults to `c === d` 15 * @returns {boolean} 16 */ 2 17 export function areArraysEqual(a, b, equalityFunction = (c, d) => { return c === d; }) { 3 18 try { -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/get-host-info.sub.js
r253683 r263621 1 /** 2 * Host information for cross-origin tests. 3 * @returns {Object} with properties for different host information. 4 */ 1 5 function get_host_info() { 2 6 … … 39 43 } 40 44 45 /** 46 * When a default port is used, location.port returns the empty string. 47 * This function attempts to provide an exact port, assuming we are running under wptserve. 48 * @param {*} loc - can be Location/<a>/<area>/URL, but assumes http/https only. 49 * @returns {string} The port number. 50 */ 41 51 function get_port(loc) { 42 // When a default port is used, location.port returns the empty string.43 // To compare with wptserve `ports` substitution we need a port...44 // loc can be Location/<a>/<area>/URL, but assumes http/https only.45 52 if (loc.port) { 46 53 return loc.port; -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/media.js
r225781 r263621 1 // 2 // Returns the URI of a supported video source based on the user agent 3 // 1 /** 2 * Returns the URL of a supported video source based on the user agent 3 * @param {string} base - media URL without file extension 4 * @returns {string} 5 */ 4 6 function getVideoURI(base) 5 7 { … … 17 19 } 18 20 19 // 20 // Returns the URI of a supported audio source based on the user agent 21 // 21 /** 22 * Returns the URL of a supported audio source based on the user agent 23 * @param {string} base - media URL without file extension 24 * @returns {string} 25 */ 22 26 function getAudioURI(base) 23 27 { … … 35 39 } 36 40 41 /** 42 * Returns the MIME type for a media URL based on the file extension. 43 * @param {string} url 44 * @returns {string} 45 */ 37 46 function getMediaContentType(url) { 38 47 var extension = new URL(url, location).pathname.split(".").pop(); -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/object-association.js
r245004 r263621 3 3 // For now this only has per-Window tests, but we could expand it to also test per-Document 4 4 5 /** 6 * Run tests for window[propertyName] after discarding the browsing context, navigating, etc. 7 * @param {string} propertyName 8 */ 5 9 window.testIsPerWindow = propertyName => { 6 10 test(t => { -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/redirect.py
r179439 r263621 7 7 """ 8 8 status = 302 9 if "status" in request.GET:9 if b"status" in request.GET: 10 10 try: 11 status = int(request.GET.first( "status"))11 status = int(request.GET.first(b"status")) 12 12 except ValueError: 13 13 pass … … 15 15 response.status = status 16 16 17 location = request.GET.first( "location")17 location = request.GET.first(b"location") 18 18 19 response.headers.set( "Location", location)19 response.headers.set(b"Location", location) -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/reftest-wait.js
r179439 r263621 1 /** 2 * Remove the `reftest-wait` class on the document element. 3 * The reftest runner will wait with taking a screenshot while 4 * this class is present. 5 * 6 * See https://web-platform-tests.org/writing-tests/reftests.html#controlling-when-comparison-occurs 7 */ 1 8 function takeScreenshot() { 2 9 document.documentElement.classList.remove("reftest-wait"); 3 10 } 4 11 12 /** 13 * Call `takeScreenshot()` after a delay of at least |timeout| milliseconds. 14 * @param {number} timeout - milliseconds 15 */ 5 16 function takeScreenshotDelayed(timeout) { 6 17 setTimeout(function() { -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/README.md
r253683 r263621 1 2 3 1 This directory contains the common infrastructure for the following tests (also referred below as projects). 4 2 … … 26 24 # Test generator 27 25 28 The test generator ( `common/security-features/tools`) generates test HTML files from templates and a seed (`spec.src.json`) that defines all the test scenarios.26 The test generator ([common/security-features/tools/generate.py](tools/generate.py)) generates test HTML files from templates and a seed (`spec.src.json`) that defines all the test scenarios. 29 27 30 28 The project (i.e. a WPT subdirectory, for example `referrer-policy/`) that uses the generator should define per-project data and invoke the common generator logic in `common/security-features/tools`. … … 35 33 common/security-features/ 36 34 └── tools/ - the common test generator logic 35 ├── spec.src.json 37 36 └── template/ - the test files templates 38 37 project-directory/ (e.g. referrer-policy/) … … 40 39 ├── generic/ 41 40 │ ├── test-case.sub.js - Per-project test helper 42 │ └── tools/43 │ └── generator.py - Per-project generator script41 │ ├── sanity-checker.js (Used by debug target only) 42 │ └── spec_json.js (Used by debug target only) 44 43 └── gen/ - generated tests 45 44 ``` 46 45 47 Invoking `project-directory/generic/tools/generate.py` will parse the spec JSON and determine which tests to generate (or skip) while using templates.48 49 46 ## Generating the tests 50 47 51 The repository already contains generated tests, so if you're making changes, see the [Removing all generated tests](#removing-all-generated-tests) section below, on how to remove them before you start generating tests which include your changes.48 Note: When the repository already contains generated tests, [remove all generated tests](#removing-all-generated-tests) first. 52 49 53 50 ```bash 54 # Chdir into the project directory.55 cd ~/web-platform-tests/project-directory 51 # Install json5 module if needed. 52 pip install --user json5 56 53 57 54 # Generate the test files under gen/ (HTMLs and .headers files). 58 ./generic/tools/generate.py 55 path/to/common/security-features/tools/generate.py --spec path/to/project-directory/ 59 56 60 57 # Add all generated tests to the repo. 61 git add gen/ && git commit -m "Add generated tests" 62 ``` 58 git add path/to/project-directory/gen/ && git commit -m "Add generated tests" 59 ``` 60 61 This will parse the spec JSON5 files and determine which tests to generate (or skip) while using templates. 62 63 - The default spec JSON5: `common/security-features/tools/spec.src.json`. 64 - Describes common configurations, such as subresource types, source context types, etc. 65 - The per-project spec JSON5: `project-directory/spec.src.json`. 66 - Describes project-specific configurations, particularly those related to test generation patterns (`specification`), policy deliveries (e.g. `delivery_type`, `delivery_value`) and `expectation`. 67 68 For how these two spec JSON5 files are merged, see [Sub projects](#sub-projects) section. 69 70 Note: `spec.src.json` is transitioning to JSON5 [#21710](https://github.com/web-platform-tests/wpt/issues/21710). 63 71 64 72 During the generation, the spec is validated by ```common/security-features/tools/spec_validator.py```. This is specially important when you're making changes to `spec.src.json`. Make sure it's a valid JSON (no comments or trailing commas). The validator reports specific errors (missing keys etc.), if any. … … 69 77 70 78 ```bash 71 # Chdir into the project directory. 72 cd ~/web-platform-tests/project-directory 73 74 # Remove all generated tests. 75 rm -r gen/ 79 rm -r path/to/project-directory/gen/ 76 80 ``` 77 81 … … 80 84 Note: this section is currently obsolete. Only the release template is working. 81 85 82 The generator script ```./generic/tools/generate.py```has two targets: ```release``` and ```debug```.86 The generator script has two targets: ```release``` and ```debug```. 83 87 84 88 * Using **release** for the target will produce tests using a template for optimizing size and performance. The release template is intended for the official web-platform-tests and possibly other test suites. No sanity checking is done in release mode. Use this option whenever you're checking into web-platform-tests. … … 87 91 88 92 Note that **release** is the default target when invoking ```generate.py```. 93 94 95 ## Sub projects 96 97 Projects can be nested, for example to reuse a single `spec.src.json` across similar but slightly different sets of generated tests. 98 The directory structure would look like: 99 100 ``` 101 project-directory/ (e.g. referrer-policy/) 102 ├── spec.src.json - Parent project's spec JSON 103 ├── generic/ 104 │ └── test-case.sub.js - Parent project's test helper 105 ├── gen/ - parent project's generated tests 106 └── sub-project-directory/ (e.g. 4K) 107 ├── spec.src.json - Child project's spec JSON 108 ├── generic/ 109 │ └── test-case.sub.js - Child project's test helper 110 └── gen/ - child project's generated tests 111 ``` 112 113 `generate.py --spec project-directory/sub-project-directory` generates test files under `project-directory/sub-project-directory/gen`, based on `project-directory/spec.src.json` and `project-directory/sub-project-directory/spec.src.json`. 114 115 - The child project's `spec.src.json` is merged into parent project's `spec.src.json`. 116 - Two spec JSON objects are merged recursively. 117 - If a same key exists in both objects, the child's value overwrites the parent's value. 118 - If both (child's and parent's) values are arrays, then the child's value is concatenated to the parent's value. 119 - For debugging, `generate.py` dumps the merged spec JSON object as `generic/debug-output.spec.src.json`. 120 - The child project's generated tests include both of the parent and child project's `test-case.sub.js`: 121 ```html 122 <script src="project-directory/test-case.sub.js"></script> 123 <script src="project-directory/sub-project-directory/test-case.sub.js"></script> 124 <script> 125 TestCase(...); 126 </script> 127 ``` 89 128 90 129 … … 130 169 * Regenerate the tests and MANIFEST.json 131 170 132 133 ## The spec JSON format 134 135 For examples of spec JSON files, see [referrer-policy/spec.src.json](../../referrer-policy/spec.src.json) or [mixed-content/spec.src.json](../../mixed-content/spec.src.json). 136 137 ### Main sections 171 ## How the generator works 172 173 This section describes how `spec.src.json` is turned into scenario data in test HTML files which are then processed by JavaScript test helpers and server-side scripts, and describes the objects/types used in the process. 174 175 ### The spec JSON 176 177 `spec.src.json` is the input for the generator that defines what to generate. For examples of spec JSON files, see [referrer-policy/spec.src.json](../../referrer-policy/spec.src.json) or [mixed-content/spec.src.json](../../mixed-content/spec.src.json). 178 179 #### Main sections 138 180 139 181 * **`specification`** … … 144 186 * **`excluded_tests`** 145 187 146 List of ```test_expansion``` patterns expanding into selections which get skipped when generating the tests (aka. bl acklisting/suppressing)188 List of ```test_expansion``` patterns expanding into selections which get skipped when generating the tests (aka. blocklisting/suppressing) 147 189 148 190 * **`test_expansion_schema`** … … 161 203 * **`source_context_list_schema`** 162 204 163 Provides possible nested combinations of source contexts. See [Source Contexts](#source-contexts) section below for details. 164 165 ### Test Expansion Patterns 166 205 Provides possible nested combinations of source contexts. See [SourceContexts Resolution](#sourcecontexts-resolution) section below for details. 206 207 ### Test Expansion Pattern Object 208 209 Test expansion patterns (`test_expansion`s in `specification` section) define the combinations of test configurations (*selections*) to be generated. 167 210 Each field in a test expansion can be in one of the following formats: 168 211 … … 173 216 * Match all: ```"*"``` 174 217 175 176 **NOTE:** An expansion is always constructive (inclusive), there isn't a negation operator for explicit exclusion. Be aware that using an empty list ```[]``` matches (expands into) exactly nothing. Tests which are to be excluded should be defined in the ```excluded_tests``` section instead. 177 178 A single test expansion pattern, be it a requirement or a suppressed pattern, gets expanded into a list of **selections** as follows: 218 The following fields have special meaning: 219 220 - **`name`**: just ignored. (Previously this was used as a part of filenames but now this is merely a label for human and is never used by generator. This field might be removed in the future (https://github.com/web-platform-tests/wpt/issues/21708)) 221 - **`expansion`**: if there is more than one pattern expanding into a same selection, the pattern appearing later in the spec JSON will overwrite a previously generated selection. To make clear this is intentional, set the value of the ```expansion``` field to ```default``` for an expansion appearing earlier and ```override``` for the one appearing later. 222 223 For example a test expansion pattern (taken from [referrer-policy/spec.src.json](../../referrer-policy/spec.src.json), sorted/formatted for explanation): 224 225 ```json 226 { 227 "name": "insecure-protocol", 228 "expansion": "default", 229 230 "delivery_type": "*", 231 "delivery_value": "no-referrer-when-downgrade", 232 "source_context_list": "*", 233 234 "expectation": "stripped-referrer", 235 "origin": ["same-http", "cross-http"], 236 "redirection": "*", 237 "source_scheme": "http", 238 "subresource": "*" 239 } 240 ``` 241 242 means: "All combinations with all possible `delivery_type`, `delivery_value`=`no-referrer-when-downgrade`, all possible `source_context_list`, `expectation`=`stripped-referrer`, `origin`=`same-http` or `cross-http`, all possible `redirection`, `source_scheme`=`http`, and all possible `subresource`. 243 244 ### Selection Object 245 246 A selection is an object that defines a single test, with keys/values from `test_expansion_schema`. 247 248 A single test expansion pattern gets expanded into a list of selections as follows: 179 249 180 250 * Expand each field's pattern (single, any of, or all) to list of allowed values (defined by the ```test_expansion_schema```) 181 251 182 * Permute - Recursively enumerate all **selections** across all fields 183 184 Be aware that if there is more than one pattern expanding into a same selection, the pattern appearing later in the spec JSON will overwrite a previously generated selection. To make sure this is not undetected when generating, set the value of the ```expansion``` field to ```default``` for an expansion appearing earlier and ```override``` for the one appearing later. 185 186 A **selection** is a single **test instance** (scenario) with explicit values that defines a single test. The scenario is then evaluated by the ```TestCase``` in JS. For the rest of the arranging part, examine ```/common/security-features/tools/generate.py``` to see how the values for the templates are produced. 187 252 * Permute - Recursively enumerate all selections across all fields 253 254 The following field has special meaning: 255 256 - **`delivery_key`**: This doesn't exist in test expansion patterns, and instead is taken from `delivery_key` field of the spec JSON and added into selections. (TODO(https://github.com/web-platform-tests/wpt/issues/21708): probably this should be added to test expansion patterns to remove this special handling) 257 258 For example, the test expansion in the example above generates selections like the following selection (which eventually generates [this test file](../../referrer-policy/gen/worker-classic.http-rp/no-referrer-when-downgrade/fetch/same-http.no-redirect.http.html )): 259 260 ```json 261 { 262 "delivery_type": "http-rp", 263 "delivery_key": "referrerPolicy", 264 "delivery_value": "no-referrer-when-downgrade", 265 "source_context_list": "worker-classic", 266 267 "expectation": "stripped-referrer", 268 "origin": "same-http", 269 "redirection": "no-redirect", 270 "source_scheme": "http", 271 "subresource": "fetch" 272 } 273 ``` 274 275 ### Excluding Test Expansion Patterns 276 277 The ```excluded_tests``` section have objects with the same format as [Test Expansion Patterns](#test-expansion-patterns) that define selections to be excluded. 188 278 189 279 Taking the spec JSON, the generator follows this algorithm: … … 191 281 * Expand all ```excluded_tests``` to create a blacklist of selections 192 282 193 * For each specification requirement: Expand the ```test_expansion``` pattern into selections and check each against the blacklist, if not marked as suppresed, generate the test resources for the selection 194 195 196 ### Source Contexts 197 198 In **`source_context_list_schema`**, we can specify 199 200 - source contexts from where subresource requests are sent, and 201 - how policies are delivered, by source contexts and/or subresource requests. 202 203 - `sourceContextList`: an array of `SourceContext` objects, and 204 - `subresourcePolicyDeliveries`: an array of `PolicyDelivery` objects. 205 206 They have the same object format as described in 207 `common/security-features/resources/common.js` comments, and are directly 208 serialized to generated HTML files and passed to JavaScript test code, 209 except that: 210 211 - The first entry of `sourceContextList`'s `sourceContextType` should be 212 always `top`, which represents the top-level generated test HTML. 213 (This entry is omitted in the JSON passed to JavaScript, but 214 the policy deliveries specified here are written as e.g. 215 `<meta>` elements in the generated test HTML or HTTP headers) 216 - Instead of `PolicyDelivery` object (in `sourceContextList` or 217 `subresourcePolicyDeliveries`), following placeholder strings can be used. 218 219 The keys of `source_context_list_schema` can be used as the values of 220 `source_context_list` fields, to indicate which source context configuration 221 to be used. 222 223 ### PolicyDelivery placeholders 224 225 Each test contains 226 227 - `delivery_key` (derived from the top-level `delivery_key`) and 228 - `delivery_value`, `delivery_type` (derived from `test_expansion`), 229 230 which represents the **target policy delivery**, the policy delivery to be 231 tested. 232 233 The following placeholder strings in `source_context_list_schema` can be used: 283 * For each `specification` entries: Expand the ```test_expansion``` pattern into selections and check each against the blacklist, if not marked as suppresed, generate the test resources for the selection 284 285 ### SourceContext Resolution 286 287 The `source_context_list_schema` section of `spec.src.json` defines templates of policy deliveries and source contexts. 288 The `source_context_list` value in a selection specifies the key of the template to be used in `source_context_list_schema`, and the following fields in the selection are filled into the template (these three values define the **target policy delivery** to be tested): 289 290 - `delivery_type` 291 - `delivery_key` 292 - `delivery_value` 293 294 #### Source Context List Schema 295 296 Each entry of **`source_context_list_schema`**, defines a single template of how/what policies to be delivered in what source contexts (See also [PolicyDelivery](types.md#policydelivery) and [SourceContext](types.md#sourcecontext)). 297 298 - The key: the name of the template which matches with the `source_context_list` value in a selection. 299 - `sourceContextList`: an array of `SourceContext` objects that represents a (possibly nested) context. 300 - `sourceContextType` of the first entry of `sourceContextList` should be always `"top"`, which represents the top-level generated test HTML. This entry is omitted in the scenario JSON object passed to JavaScript runtime, but the policy deliveries specified here are handled by the generator, e.g. written as `<meta>` elements in the generated test HTML. 301 - `subresourcePolicyDeliveries`: an array of `PolicyDelivery` objects that represents policies specified at subresource requests (e.g. `referrerPolicy` attribute of `<img>` elements). 302 303 #### PolicyDelivery placeholders 304 305 Instead to ordinal `PolicyDelivery` objects, the following placeholder strings can be used in `sourceContextList` or `subresourcePolicyDeliveries`. 234 306 235 307 - `"policy"`: 236 308 - Replaced with the target policy delivery. 237 - Can be used to specify where the target policy delivery should be238 delivered.239 309 - `"policyIfNonNull"`: 240 - Replaced with the target policy delivery, only if it has non-null value.241 If the value is null, then the test fileis not generated.310 - Replaced with the target policy delivery, only if `delivery_value` is not `null`. 311 If `delivery_value` is `null`, then the test is not generated. 242 312 - `"anotherPolicy"`: 243 313 - Replaced with a `PolicyDelivery` object that has a different value from … … 246 316 the target policy delivery. 247 317 248 For example, when the target policy delivery is 249 `{deliveryType: "http-rp", key: "referrerPolicy", value: "no-referrer"}`, 250 251 ```json 252 "sourceContextList": [ 253 { 254 "sourceContextType": "top", 255 "policyDeliveries": [ 256 "anotherPolicy" 257 ] 258 }, 259 { 260 "sourceContextType": "classic-worker", 261 "policyDeliveries": [ 262 "policy" 263 ] 264 } 265 ] 266 ``` 267 268 is replaced with 269 270 ```json 271 "sourceContextList": [ 272 { 273 "sourceContextType": "top", 274 "policyDeliveries": [ 275 { 276 "deliveryType": "meta", 277 "key": "referrerPolicy", 278 "value": "unsafe-url" 279 } 280 ] 281 }, 282 { 283 "sourceContextType": "classic-worker", 284 "policyDeliveries": [ 285 { 286 "deliveryType": "http-rp", 287 "key": "referrerPolicy", 288 "value": "no-referrer" 289 } 290 ] 291 } 292 ] 293 ``` 294 295 which indicates 296 297 - The top-level Document has `<meta name="referrer" content="unsafe-url">`. 298 - The classic worker is created with 299 `Referrer-Policy: no-referrer` HTTP response headers. 300 301 ### `source_context_schema` and `subresource_schema` 318 #### `source_context_schema` and `subresource_schema` 302 319 303 320 These represent supported delivery types and subresources … … 305 322 306 323 - To filter out test files for unsupported combinations of delivery types, 307 source contexts and subresources .308 - To determine what delivery types shouldbe used for `anotherPolicy`324 source contexts and subresources during SourceContext resolution. 325 - To determine what delivery types can be used for `anotherPolicy` 309 326 placeholder. 327 328 #### Example 329 330 For example, the following entry in `source_context_list_schema`: 331 332 ```json 333 "worker-classic": { 334 "sourceContextList": [ 335 { 336 "sourceContextType": "top", 337 "policyDeliveries": [ 338 "anotherPolicy" 339 ] 340 }, 341 { 342 "sourceContextType": "worker-classic", 343 "policyDeliveries": [ 344 "policy" 345 ] 346 } 347 ], 348 "subresourcePolicyDeliveries": [] 349 } 350 ``` 351 352 Defines a template to be instantiated with `delivery_key`, `delivery_type` and `delivery_value` values defined outside `source_context_list_schema`, which reads: 353 354 - A classic `WorkerGlobalScope` is created under the top-level Document, and has a policy defined by `delivery_key`, `delivery_type` and `delivery_value`. 355 - The top-level Document has a policy different from the policy given to the classic worker (to confirm that the policy of the classic worker, not of the top-level Document, is used). 356 - The subresource request is sent from the classic `WorkerGlobalScope`, with no additional policies specified at the subresource request. 357 358 And when filled with the following values from a selection: 359 360 - `delivery_type`: `"http-rp"` 361 - `delivery_key`: `"referrerPolicy"` 362 - `delivery_value`: `"no-referrer-when-downgrade"` 363 364 This becomes: 365 366 ```json 367 "worker-classic": { 368 "sourceContextList": [ 369 { 370 "sourceContextType": "top", 371 "policyDeliveries": [ 372 { 373 "deliveryType": "meta", 374 "key": "referrerPolicy", 375 "value": "no-referrer" 376 } 377 ] 378 }, 379 { 380 "sourceContextType": "worker-classic", 381 "policyDeliveries": [ 382 { 383 "deliveryType": "http-rp", 384 "key": "referrerPolicy", 385 "value": "no-referrer-when-downgrade" 386 } 387 ] 388 } 389 ], 390 "subresourcePolicyDeliveries": [] 391 } 392 ``` 393 394 which means 395 396 - The top-level Document has `<meta name="referrer" content="no-referrer">`. 397 - The classic worker is created with 398 `Referrer-Policy: no-referrer-when-downgrade` HTTP response headers. 399 400 ### Scenario Object 401 402 The **scenario** object is the JSON object written to the generated HTML files, and passed to JavaScript test runtime (as an argument of `TestCase`). 403 A scenario object is an selection object, minus the keys used in [SourceContext Resolution](#sourceContext-resolution): 404 405 - `source_context_list` 406 - `delivery_type` 407 - `delivery_key` 408 - `delivery_value` 409 410 plus the keys instantiated by [SourceContext Resolution](#sourceContext-resolution): 411 412 - `source_context_list`, except for the first `"top"` entry. 413 - `subresource_policy_deliveries` 414 415 For example: 416 417 ```json 418 { 419 "source_context_list": [ 420 { 421 "sourceContextType": "worker-classic", 422 "policyDeliveries": [ 423 { 424 "deliveryType": "http-rp", 425 "key": "referrerPolicy", 426 "value": "no-referrer-when-downgrade" 427 } 428 ] 429 } 430 ], 431 "subresource_policy_deliveries": [], 432 433 "expectation": "stripped-referrer", 434 "origin": "same-http", 435 "redirection": "no-redirect", 436 "source_scheme": "http", 437 "subresource": "fetch" 438 } 439 ``` 440 441 ### TopLevelPolicyDelivery Object 442 443 The ***TopLevelPolicyDelivery** object is the first `"top"` entry of `SourceContextList` instantiated by [SourceContext Resolution](#sourceContext-resolution), which represents the policy delivery of the top-level HTML Document. 444 445 The generator generates `<meta>` elements and `.headers` files of the top-level HTML files from the TopLevelPolicyDelivery object. 446 447 This is handled separately by the generator from other parts of selection objects and scenario objects, because the `<meta>` and `.headers` are hard-coded directly to the files in the WPT repository, while policies of subcontexts are generated via server-side `common/security-features/scope` scripts. 448 449 TODO(https://github.com/web-platform-tests/wpt/issues/21710): Currently the name `TopLevelPolicyDelivery` doesn't appear in the code. 450 451 ## How the test runtime works 452 453 All the information needed at runtime is contained in an scenario object. See the code/comments of the following files. 454 455 - `project-directory/generic/test-case.js` defines `TestCase`, the entry point that receives a scenario object. `resources/common.sub.js` does the most of common JavaScript work. 456 - Subresource URLs (which point to `subresource/` scripts) are calculated from `origin` and `redirection` values. 457 - Initiating fetch requests based on `subresource` and `subresource_policy_deliveries`. 458 - `scope/` server-side scripts serve non-toplevel contexts, while the top-level Document is generated by the generator. 459 TODO(https://github.com/web-platform-tests/wpt/issues/21709): Merge the logics of `scope/` and the generator. 460 - `subresource/` server-side scripts serve subresource responses. -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/resources/common.sub.js
r253683 r263621 14 14 // The objects are represented as JSON objects (not JavaScript/Python classes 15 15 // in a strict sense) to be passed between JavaScript/Python code. 16 17 // Note: So far this document covers: 18 // - resources/common.sub.js : client-side test infra code 19 // - scope/ - server-side scripts that serves nested source contexts 20 // but doesn't cover: 21 // - tools/ - generator scripts that generates top-level HTML documents. 22 // There are some policies only handled by generators (e.g. mixed-content 23 // opt-ins) and not yet covered by the docs here. 16 // 17 // See also common/security-features/Types.md for high-level description. 24 18 25 19 /** … … 93 87 @typedef SourceContext 94 88 @type {object} 95 Requests can be possibly sent from various kinds of source contexts, i.e.96 fetch client's environment settings objects:97 top-level windows, iframes, or workers.98 A SourceContext object specifies one environment settings object, and99 an Array<SourceContext> specifies a possibly nested context,100 from the outer-most to inner-most environment settings objects.101 102 For example:103 [{sourceContextType: "srcdoc"}, {sourceContextType: "worker-classic"}]104 means that a subresource request is to be sent from105 a classic dedicated worker created from <iframe srcdoc>106 inside the top-level HTML document.107 Note: the top-level document is not included in the array and108 is assumed implicitly.109 110 SourceContext (or Array<SourceContext>) is set based on111 the fetch client's settings object that is used for the subresource request,112 NOT on module map settings object, and113 NOT on the inner-most settings object that appears in the test.114 For example, Array<SourceContext> is `[]` (indicating the top Window)115 for `worker.js`116 - When it is the root worker script: `new Worker('worker.js')`, or117 - When it is imported from the root worker script:118 `new Worker('top.js', {type: 'module'})`119 where `top.js` has `import 'worker.js'`.120 because the request for `worker.js` uses the Window as its fetch client's121 settings object, while a WorkerGlobalScope is created though.122 89 123 90 @property {string} sourceContextType … … 399 366 requestViaScript 2 Y Y - 400 367 requestViaSendBeacon 3 - Y - 401 requestViaSharedWorker 2 Y - -368 requestViaSharedWorker 2 Y Y Y 402 369 requestViaVideo 3 - Y - 403 370 requestViaWebSocket 3 - Y - … … 520 487 521 488 function workerUrlThatImports(url) { 489 return `/common/security-features/subresource/static-import.py` + 490 `?import_url=${encodeURIComponent(url)}`; 491 } 492 493 function workerDataUrlThatImports(url) { 522 494 return `data:text/javascript,import '${url}';`; 523 495 } … … 543 515 } 544 516 545 function requestViaSharedWorker(url ) {517 function requestViaSharedWorker(url, options) { 546 518 var worker; 547 519 try { 548 worker = new SharedWorker(url );520 worker = new SharedWorker(url, options); 549 521 } catch(e) { 550 522 return Promise.reject(e); … … 912 884 invoker: url => requestViaDedicatedWorker(url, {type: "module"}), 913 885 }, 886 "worker-import": { 887 path: "/common/security-features/subresource/worker.py", 888 invoker: url => 889 requestViaDedicatedWorker(workerUrlThatImports(url), {type: "module"}), 890 }, 914 891 "worker-import-data": { 915 892 path: "/common/security-features/subresource/worker.py", 916 893 invoker: url => 917 requestViaDedicatedWorker(worker UrlThatImports(url), {type: "module"}),894 requestViaDedicatedWorker(workerDataUrlThatImports(url), {type: "module"}), 918 895 }, 919 896 "sharedworker-classic": { 920 897 path: "/common/security-features/subresource/shared-worker.py", 921 invoker: requestViaSharedWorker, 898 invoker: url => requestViaSharedWorker(url), 899 }, 900 "sharedworker-module": { 901 path: "/common/security-features/subresource/shared-worker.py", 902 invoker: url => requestViaSharedWorker(url, {type: "module"}), 903 }, 904 "sharedworker-import": { 905 path: "/common/security-features/subresource/shared-worker.py", 906 invoker: url => 907 requestViaSharedWorker(workerUrlThatImports(url), {type: "module"}), 908 }, 909 "sharedworker-import-data": { 910 path: "/common/security-features/subresource/shared-worker.py", 911 invoker: url => 912 requestViaSharedWorker(workerDataUrlThatImports(url), {type: "module"}), 922 913 }, 923 914 … … 935 926 path: "/common/security-features/subresource/worker.py", 936 927 invoker: url => 937 requestViaWorklet(workletType, worker UrlThatImports(url))928 requestViaWorklet(workletType, workerDataUrlThatImports(url)) 938 929 }; 939 930 } … … 1121 1112 "worker-classic": { 1122 1113 // Classic dedicated worker loaded from same-origin. 1123 invoker: invokeFromWorker.bind(undefined, false, {}),1114 invoker: invokeFromWorker.bind(undefined, "worker", false, {}), 1124 1115 }, 1125 1116 "worker-classic-data": { 1126 1117 // Classic dedicated worker loaded from data: URL. 1127 invoker: invokeFromWorker.bind(undefined, true, {}),1118 invoker: invokeFromWorker.bind(undefined, "worker", true, {}), 1128 1119 }, 1129 1120 "worker-module": { 1130 1121 // Module dedicated worker loaded from same-origin. 1131 invoker: invokeFromWorker.bind(undefined, false, {type: 'module'}),1122 invoker: invokeFromWorker.bind(undefined, "worker", false, {type: 'module'}), 1132 1123 }, 1133 1124 "worker-module-data": { 1134 1125 // Module dedicated worker loaded from data: URL. 1135 invoker: invokeFromWorker.bind(undefined, true, {type: 'module'}), 1126 invoker: invokeFromWorker.bind(undefined, "worker", true, {type: 'module'}), 1127 }, 1128 "sharedworker-classic": { 1129 // Classic shared worker loaded from same-origin. 1130 invoker: invokeFromWorker.bind(undefined, "sharedworker", false, {}), 1131 }, 1132 "sharedworker-classic-data": { 1133 // Classic shared worker loaded from data: URL. 1134 invoker: invokeFromWorker.bind(undefined, "sharedworker", true, {}), 1135 }, 1136 "sharedworker-module": { 1137 // Module shared worker loaded from same-origin. 1138 invoker: invokeFromWorker.bind(undefined, "sharedworker", false, {type: 'module'}), 1139 }, 1140 "sharedworker-module-data": { 1141 // Module shared worker loaded from data: URL. 1142 invoker: invokeFromWorker.bind(undefined, "sharedworker", true, {type: 'module'}), 1136 1143 }, 1137 1144 }; … … 1154 1161 1155 1162 /** 1163 @param {string} workerType 1164 "worker" (for dedicated worker) or "sharedworker". 1156 1165 @param {boolean} isDataUrl 1157 1166 true if the worker script is loaded from data: URL. … … 1162 1171 Other parameters and return values are the same as those of invokeRequest(). 1163 1172 */ 1164 function invokeFromWorker( isDataUrl, workerOptions,1173 function invokeFromWorker(workerType, isDataUrl, workerOptions, 1165 1174 subresource, sourceContextList) { 1166 1175 const currentSourceContext = sourceContextList[0]; … … 1186 1195 return promise 1187 1196 .then(url => { 1188 const worker = new Worker(url, workerOptions); 1189 worker.postMessage({subresource: subresource, 1190 sourceContextList: sourceContextList.slice(1)}); 1191 return bindEvents2(worker, "message", worker, "error", window, "error"); 1197 if (workerType === "worker") { 1198 const worker = new Worker(url, workerOptions); 1199 worker.postMessage({subresource: subresource, 1200 sourceContextList: sourceContextList.slice(1)}); 1201 return bindEvents2(worker, "message", worker, "error", window, "error"); 1202 } else if (workerType === "sharedworker") { 1203 const worker = new SharedWorker(url, workerOptions); 1204 worker.port.start(); 1205 worker.port.postMessage({subresource: subresource, 1206 sourceContextList: sourceContextList.slice(1)}); 1207 return bindEvents2(worker.port, "message", worker, "error", window, "error"); 1208 } else { 1209 throw new Error('Invalid worker type: ' + workerType); 1210 } 1192 1211 }) 1193 1212 .then(event => { -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/scope/template/worker.js.template
r253683 r263621 1 1 %(import)s 2 2 3 if ('DedicatedWorkerGlobalScope' in self && 4 self instanceof DedicatedWorkerGlobalScope) { 5 self.onmessage = event => onMessageFromParent(event, self); 6 } else if ('SharedWorkerGlobalScope' in self && 7 self instanceof SharedWorkerGlobalScope) { 8 onconnect = event => { 9 const port = event.ports[0]; 10 port.onmessage = event => onMessageFromParent(event, port); 11 }; 12 } 13 3 14 // Receive a message from the parent and start the test. 4 function onMessageFromParent(event) { 5 // Because this window might receive messages from child context during 6 // tests, we first remove the listener here before staring the test. 7 self.removeEventListener('message', onMessageFromParent); 8 15 function onMessageFromParent(event, port) { 9 16 const configurationError = "%(error)s"; 10 17 if (configurationError.length > 0) { 11 po stMessage({error: configurationError});18 port.postMessage({error: configurationError}); 12 19 return; 13 20 } … … 15 22 invokeRequest(event.data.subresource, 16 23 event.data.sourceContextList) 17 .then(result => po stMessage(result))24 .then(result => port.postMessage(result)) 18 25 .catch(e => { 19 26 const message = (e.error && e.error.stack) || e.message || "Error"; 20 po stMessage({error: message});27 port.postMessage({error: message}); 21 28 }); 22 29 } 23 24 self.addEventListener('message', onMessageFromParent); -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/scope/worker.py
r253683 r263621 24 24 if delivery['key'] == 'referrerPolicy': 25 25 maybe_additional_headers['Referrer-Policy'] = delivery['value'] 26 elif delivery['key'] == 'mixedContent' and delivery['value'] == 'opt-in': 27 maybe_additional_headers['Content-Security-Policy'] = 'block-all-mixed-content' 28 elif delivery['key'] == 'upgradeInsecureRequests' and delivery['value'] == 'upgrade': 29 maybe_additional_headers['Content-Security-Policy'] = 'upgrade-insecure-requests' 26 30 else: 27 31 error = 'invalid delivery key for http-rp: %s' % delivery['key'] -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/template/w3c-import.log
r245004 r263621 20 20 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/template/script.js.template 21 21 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/template/shared-worker.js.template 22 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/template/static-import.js.template 22 23 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/template/svg.css.template 23 24 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/template/svg.embedded.template -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/w3c-import.log
r245004 r263621 21 21 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/font.py 22 22 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/image.py 23 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/referrer.py 23 24 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/script.py 24 25 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/shared-worker.py 26 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/static-import.py 25 27 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/stylesheet.py 26 28 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/subresource/subresource.py -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/format_spec_src_json.py
r253683 r263621 8 8 script_directory = os.path.dirname(os.path.abspath(__file__)) 9 9 for dir in [ 10 'mixed-content', 'referrer-policy', 'upgrade-insecure-requests' 10 'mixed-content', 'referrer-policy', 'referrer-policy/4K-1', 11 'referrer-policy/4K', 'referrer-policy/4K+1', 12 'upgrade-insecure-requests' 11 13 ]: 12 14 filename = os.path.join(script_directory, '..', '..', '..', dir, -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/generate.py
r253683 r263621 1 #!/usr/bin/env python 2 1 3 from __future__ import print_function 2 4 3 5 import argparse 6 import collections 4 7 import copy 5 8 import json … … 52 55 53 56 # Dumps the test config `selection` into a serialized JSON string. 54 # We omit `name` parameter because it is not used by tests.55 57 def dump_test_parameters(selection): 56 selection = dict(selection)57 del selection['name']58 59 58 return json.dumps( 60 59 selection, … … 65 64 66 65 67 def get_test_filename( config, selection):66 def get_test_filename(spec_directory, spec_json, selection): 68 67 '''Returns the filname for the main test HTML file''' 69 68 … … 73 72 selection_for_filename['delivery_value'] = 'unset' 74 73 75 return os.path.join(config.spec_directory, 76 config.test_file_path_pattern % selection_for_filename) 74 return os.path.join( 75 spec_directory, 76 spec_json['test_file_path_pattern'] % selection_for_filename) 77 77 78 78 … … 128 128 129 129 130 def generate_selection(spec_json, config, selection, spec, 131 test_html_template_basename): 132 test_filename = get_test_filename(config, selection) 130 def generate_selection(spec_json, selection): 131 ''' 132 Returns a scenario object (with a top-level source_context_list entry, 133 which will be removed in generate_test_file() later). 134 ''' 133 135 134 136 target_policy_delivery = util.PolicyDelivery(selection['delivery_type'], … … 165 167 ['supported_delivery_type'][selection['subresource']]) 166 168 169 # Generate per-scenario test description. 170 selection['test_description'] = spec_json[ 171 'test_description_template'] % selection 172 173 return selection 174 175 176 def generate_test_file(spec_directory, test_helper_filenames, 177 test_html_template_basename, test_filename, scenarios): 178 ''' 179 Generates a test HTML file (and possibly its associated .headers file) 180 from `scenarios`. 181 ''' 182 183 # Scenarios for the same file should have the same `source_context_list`, 184 # including the top-level one. 185 # Note: currently, non-top-level source contexts aren't necessarily required 186 # to be the same, but we set this requirement as it will be useful e.g. when 187 # we e.g. reuse a worker among multiple scenarios. 188 for scenario in scenarios: 189 assert (scenario['source_context_list'] == scenarios[0] 190 ['source_context_list']) 191 167 192 # We process the top source context below, and do not include it in 168 # `scenario` field in JavaScript.169 top_source_context = s election['source_context_list'].pop(0)193 # the JSON objects (i.e. `scenarios`) in generated HTML files. 194 top_source_context = scenarios[0]['source_context_list'].pop(0) 170 195 assert (top_source_context.source_context_type == 'top') 171 172 # Adjust the template for the test invoking JS. Indent it to look nice. 173 indent = "\n" + " " * 8 174 selection['scenario'] = dump_test_parameters(selection).replace( 175 "\n", indent) 176 177 selection['spec_name'] = spec['name'] 178 selection[ 179 'test_page_title'] = config.test_page_title_template % spec['title'] 180 selection['spec_description'] = spec['description'] 181 selection['spec_specification_url'] = spec['specification_url'] 182 selection['helper_js'] = config.helper_js 183 selection['sanity_checker_js'] = config.sanity_checker_js 184 selection['spec_json_js'] = config.spec_json_js 196 for scenario in scenarios[1:]: 197 assert (scenario['source_context_list'].pop(0) == top_source_context) 198 199 parameters = {} 200 201 # Sort scenarios, to avoid unnecessary diffs due to different orders in 202 # `scenarios`. 203 serialized_scenarios = sorted( 204 [dump_test_parameters(scenario) for scenario in scenarios]) 205 206 parameters['scenarios'] = ",\n".join(serialized_scenarios).replace( 207 "\n", "\n" + " " * 10) 208 209 test_directory = os.path.dirname(test_filename) 210 211 parameters['helper_js'] = "" 212 for test_helper_filename in test_helper_filenames: 213 parameters['helper_js'] += ' <script src="%s"></script>\n' % ( 214 os.path.relpath(test_helper_filename, test_directory)) 215 parameters['sanity_checker_js'] = os.path.relpath( 216 os.path.join(spec_directory, 'generic', 'sanity-checker.js'), 217 test_directory) 218 parameters['spec_json_js'] = os.path.relpath( 219 os.path.join(spec_directory, 'generic', 'spec_json.js'), 220 test_directory) 185 221 186 222 test_headers_filename = test_filename + ".headers" 187 test_directory = os.path.dirname(test_filename)188 223 189 224 test_html_template = util.get_template(test_html_template_basename) … … 195 230 % {'generating_script_filename': os.path.relpath(sys.argv[0], 196 231 util.test_root_directory), 197 ' html_template_filename': os.path.relpath(html_template_filename,198 232 'spec_directory': os.path.relpath(spec_directory, 233 util.test_root_directory)} 199 234 200 235 # Adjust the template for the test invoking JS. Indent it to look nice. 201 selection['generated_disclaimer'] = generated_disclaimer.rstrip() 202 selection[ 203 'test_description'] = config.test_description_template % selection 204 selection['test_description'] = \ 205 selection['test_description'].rstrip().replace("\n", "\n" + " " * 33) 236 parameters['generated_disclaimer'] = generated_disclaimer.rstrip() 206 237 207 238 # Directory for the test files. … … 218 249 f.write('%s: %s\n' % (header, delivery['headers'][header])) 219 250 220 selection['meta_delivery_method'] = delivery['meta']251 parameters['meta_delivery_method'] = delivery['meta'] 221 252 # Obey the lint and pretty format. 222 if len( selection['meta_delivery_method']) > 0:223 selection['meta_delivery_method'] = "\n " + \224 selection['meta_delivery_method']253 if len(parameters['meta_delivery_method']) > 0: 254 parameters['meta_delivery_method'] = "\n " + \ 255 parameters['meta_delivery_method'] 225 256 226 257 # Write out the generated HTML file. 227 util.write_file(test_filename, test_html_template % selection) 228 229 230 def generate_test_source_files(config, spec_json, target): 258 util.write_file(test_filename, test_html_template % parameters) 259 260 261 def generate_test_source_files(spec_directory, test_helper_filenames, 262 spec_json, target): 231 263 test_expansion_schema = spec_json['test_expansion_schema'] 232 264 specification = spec_json['specification'] 233 265 234 spec_json_js_template = util.get_template('spec_json.js.template') 235 generated_spec_json_filename = os.path.join(config.spec_directory, 236 "spec_json.js") 237 util.write_file( 238 generated_spec_json_filename, 239 spec_json_js_template % {'spec_json': json.dumps(spec_json)}) 266 if target == "debug": 267 spec_json_js_template = util.get_template('spec_json.js.template') 268 util.write_file( 269 os.path.join(spec_directory, "generic", "spec_json.js"), 270 spec_json_js_template % {'spec_json': json.dumps(spec_json)}) 271 util.write_file( 272 os.path.join(spec_directory, "generic", 273 "debug-output.spec.src.json"), 274 json.dumps(spec_json, indent=2, separators=(',', ': '))) 240 275 241 276 # Choose a debug/release template depending on the target. 242 277 html_template = "test.%s.html.template" % target 243 278 244 artifact_order = test_expansion_schema.keys() + ['name']279 artifact_order = test_expansion_schema.keys() 245 280 artifact_order.remove('expansion') 246 281 282 excluded_selection_pattern = '' 283 for key in artifact_order: 284 excluded_selection_pattern += '%(' + key + ')s/' 285 247 286 # Create list of excluded tests. 248 exclusion_dict = {}287 exclusion_dict = set() 249 288 for excluded_pattern in spec_json['excluded_tests']: 250 289 excluded_expansion = \ … … 252 291 for excluded_selection in permute_expansion(excluded_expansion, 253 292 artifact_order): 254 excluded_selection_path = config.selection_pattern % excluded_selection 255 exclusion_dict[excluded_selection_path] = True 293 excluded_selection['delivery_key'] = spec_json['delivery_key'] 294 exclusion_dict.add(excluded_selection_pattern % excluded_selection) 295 296 # `scenarios[filename]` represents the list of scenario objects to be 297 # generated into `filename`. 298 scenarios = {} 256 299 257 300 for spec in specification: … … 265 308 for selection in permute_expansion(expansion, artifact_order): 266 309 selection['delivery_key'] = spec_json['delivery_key'] 267 selection_path = config.selection_pattern % selection 268 if not selection_path in exclusion_dict: 269 if selection_path in output_dict: 270 if expansion_pattern['expansion'] != 'override': 271 print( 272 "Error: %s's expansion is default but overrides %s" 273 % (selection['name'], 274 output_dict[selection_path]['name'])) 275 sys.exit(1) 276 output_dict[selection_path] = copy.deepcopy(selection) 277 else: 278 print('Excluding selection:', selection_path) 310 selection_path = spec_json['selection_pattern'] % selection 311 if selection_path in output_dict: 312 if expansion_pattern['expansion'] != 'override': 313 print("Error: expansion is default in:") 314 print(dump_test_parameters(selection)) 315 print("but overrides:") 316 print(dump_test_parameters( 317 output_dict[selection_path])) 318 sys.exit(1) 319 output_dict[selection_path] = copy.deepcopy(selection) 279 320 280 321 for selection_path in output_dict: 281 322 selection = output_dict[selection_path] 323 if (excluded_selection_pattern % selection) in exclusion_dict: 324 print('Excluding selection:', selection_path) 325 continue 282 326 try: 283 generate_selection(spec_json, config, selection, spec, 284 html_template) 327 test_filename = get_test_filename(spec_directory, spec_json, 328 selection) 329 scenario = generate_selection(spec_json, selection) 330 scenarios[test_filename] = scenarios.get(test_filename, 331 []) + [scenario] 285 332 except util.ShouldSkip: 286 333 continue 287 334 288 289 def main(config): 335 for filename in scenarios: 336 generate_test_file(spec_directory, test_helper_filenames, 337 html_template, filename, scenarios[filename]) 338 339 340 def merge_json(base, child): 341 for key in child: 342 if key not in base: 343 base[key] = child[key] 344 continue 345 # `base[key]` and `child[key]` both exists. 346 if isinstance(base[key], list) and isinstance(child[key], list): 347 base[key].extend(child[key]) 348 elif isinstance(base[key], dict) and isinstance(child[key], dict): 349 merge_json(base[key], child[key]) 350 else: 351 base[key] = child[key] 352 353 354 def main(): 290 355 parser = argparse.ArgumentParser( 291 356 description='Test suite generator utility') … … 301 366 '--spec', 302 367 type=str, 303 default= None,368 default=os.getcwd(), 304 369 help='Specify a file used for describing and generating the tests') 305 370 # TODO(kristijanburnik): Add option for the spec_json file. 306 371 args = parser.parse_args() 307 372 308 if args.spec: 309 config.spec_directory = args.spec 310 311 spec_filename = os.path.join(config.spec_directory, "spec.src.json") 312 spec_json = util.load_spec_json(spec_filename) 373 spec_directory = os.path.abspath(args.spec) 374 375 # Read `spec.src.json` files, starting from `spec_directory`, and 376 # continuing to parent directories as long as `spec.src.json` exists. 377 spec_filenames = [] 378 test_helper_filenames = [] 379 spec_src_directory = spec_directory 380 while len(spec_src_directory) >= len(util.test_root_directory): 381 spec_filename = os.path.join(spec_src_directory, "spec.src.json") 382 if not os.path.exists(spec_filename): 383 break 384 spec_filenames.append(spec_filename) 385 test_filename = os.path.join(spec_src_directory, 'generic', 386 'test-case.sub.js') 387 assert (os.path.exists(test_filename)) 388 test_helper_filenames.append(test_filename) 389 spec_src_directory = os.path.abspath( 390 os.path.join(spec_src_directory, "..")) 391 392 spec_filenames = list(reversed(spec_filenames)) 393 test_helper_filenames = list(reversed(test_helper_filenames)) 394 395 if len(spec_filenames) == 0: 396 print('Error: No spec.src.json is found at %s.' % spec_directory) 397 return 398 399 # Load the default spec JSON file, ... 400 default_spec_filename = os.path.join(util.script_directory, 401 'spec.src.json') 402 spec_json = collections.OrderedDict() 403 if os.path.exists(default_spec_filename): 404 spec_json = util.load_spec_json(default_spec_filename) 405 406 # ... and then make spec JSON files in subdirectories override the default. 407 for spec_filename in spec_filenames: 408 child_spec_json = util.load_spec_json(spec_filename) 409 merge_json(spec_json, child_spec_json) 410 313 411 spec_validator.assert_valid_spec_json(spec_json) 314 315 generate_test_source_files(config, spec_json, args.target) 412 generate_test_source_files(spec_directory, test_helper_filenames, 413 spec_json, args.target) 414 415 416 if __name__ == '__main__': 417 main() -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/spec_validator.py
r253683 r263621 88 88 details['object'] = spec_json 89 89 assert_contains_only_fields(spec_json, [ 90 "selection_pattern", "test_file_path_pattern", 91 "test_description_template", "test_page_title_template", 90 92 "specification", "delivery_key", "subresource_schema", 91 93 "source_context_schema", "source_context_list_schema", … … 100 102 excluded_tests = spec_json['excluded_tests'] 101 103 102 valid_test_expansion_fields = ['name'] +test_expansion_schema.keys()104 valid_test_expansion_fields = test_expansion_schema.keys() 103 105 104 106 # Should be consistent with `sourceContextMap` in … … 106 108 valid_source_context_names = [ 107 109 "top", "iframe", "iframe-blank", "srcdoc", "worker-classic", 108 "worker-module", "worker-classic-data", "worker-module-data" 110 "worker-module", "worker-classic-data", "worker-module-data", 111 "sharedworker-classic", "sharedworker-module", 112 "sharedworker-classic-data", "sharedworker-module-data" 109 113 ] 110 114 … … 133 137 # Validate required fields for a single spec. 134 138 assert_contains_only_fields(spec, [ 135 'name', 'title', 'description', 'specification_url', 136 'test_expansion' 139 'title', 'description', 'specification_url', 'test_expansion' 137 140 ]) 138 assert_non_empty_string(spec, 'name')139 141 assert_non_empty_string(spec, 'title') 140 142 assert_non_empty_string(spec, 'description') … … 142 144 assert_non_empty_list(spec, 'test_expansion') 143 145 144 # Validate spec's test expansion.145 used_spec_names = {}146 147 146 for spec_exp in spec['test_expansion']: 148 147 details['object'] = spec_exp 149 assert_non_empty_string(spec_exp, 'name')150 # The name is unique in same expansion group.151 assert_value_unique_in((spec_exp['expansion'], spec_exp['name']),152 used_spec_names)153 148 assert_contains_only_fields(spec_exp, valid_test_expansion_fields) 154 149 -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/template/disclaimer.template
r245004 r263621 1 <!-- DO NOT EDIT! Generated by %(generating_script_filename)s using %(html_template_filename)s.-->1 <!-- DO NOT EDIT! Generated by `%(generating_script_filename)s --spec %(spec_directory)s/` --> -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/template/test.debug.html.template
r253683 r263621 3 3 <html> 4 4 <head> 5 <title>%(test_page_title)s</title> 6 <meta charset='utf-8'> 7 <meta name="description" content="%(spec_description)s"> 8 <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org"> 9 <link rel="help" href="%(spec_specification_url)s"> 10 <meta name="assert" content="%(test_description)s">%(meta_delivery_method)s 5 <meta charset="utf-8"> 6 <meta name="timeout" content="long">%(meta_delivery_method)s 11 7 <script src="/resources/testharness.js"></script> 12 8 <script src="/resources/testharnessreport.js"></script> … … 16 12 <!-- Internal checking of the tests --> 17 13 <script src="%(sanity_checker_js)s"></script> 18 <script src="%(helper_js)s"></script> 19 </head> 14 %(helper_js)s </head> 20 15 <body> 21 16 <script> 22 17 TestCase( 23 %(scenario)s, 24 document.querySelector("meta[name=assert]").content, 18 [ 19 %(scenarios)s 20 ], 25 21 new SanityChecker() 26 22 ).start(); 27 23 </script> 28 24 <div id="log"></div> 29 25 </body> -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/template/test.release.html.template
r253683 r263621 3 3 <html> 4 4 <head> 5 <title>%(test_page_title)s</title> 6 <meta charset='utf-8'> 7 <meta name="description" content="%(spec_description)s"> 8 <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org"> 9 <link rel="help" href="%(spec_specification_url)s"> 10 <meta name="assert" content="%(test_description)s">%(meta_delivery_method)s 5 <meta charset="utf-8"> 6 <meta name="timeout" content="long">%(meta_delivery_method)s 11 7 <script src="/resources/testharness.js"></script> 12 8 <script src="/resources/testharnessreport.js"></script> 13 9 <script src="/common/security-features/resources/common.sub.js"></script> 14 <script src="%(helper_js)s"></script> 15 </head> 10 %(helper_js)s </head> 16 11 <body> 17 12 <script> 18 13 TestCase( 19 %(scenario)s, 20 document.querySelector("meta[name=assert]").content, 14 [ 15 %(scenarios)s 16 ], 21 17 new SanityChecker() 22 18 ).start(); 23 19 </script> 24 20 <div id="log"></div> 25 21 </body> -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/util.py
r253683 r263621 1 1 from __future__ import print_function 2 2 3 import os, sys, json, re 3 import os, sys, json, json5, re 4 import collections 4 5 5 6 script_directory = os.path.dirname(os.path.abspath(__file__)) … … 31 32 with open(path_to_spec, "r") as f: 32 33 try: 33 return json .load(f)34 return json5.load(f, object_pairs_hook=collections.OrderedDict) 34 35 except ValueError as ex: 35 36 print(ex.message) … … 67 68 self.key = key 68 69 self.value = value 70 71 def __eq__(self, other): 72 return type(self) is type(other) and self.__dict__ == other.__dict__ 69 73 70 74 @classmethod … … 121 125 policy_delivery = target_policy_delivery.get_another_policy( 122 126 supported_delivery_types[0]) 123 elif type(obj) == dict:127 elif isinstance(obj, dict): 124 128 policy_delivery = PolicyDelivery(obj['deliveryType'], obj['key'], 125 129 obj['value']) … … 148 152 else: 149 153 return PolicyDelivery(delivery_type, self.key, 'no-referrer') 154 elif self.key == 'mixedContent': 155 if self.value == 'opt-in': 156 return PolicyDelivery(delivery_type, self.key, None) 157 else: 158 return PolicyDelivery(delivery_type, self.key, 'opt-in') 159 elif self.key == 'upgradeInsecureRequests': 160 if self.value == 'upgrade': 161 return PolicyDelivery(delivery_type, self.key, None) 162 else: 163 return PolicyDelivery(delivery_type, self.key, 'upgrade') 150 164 else: 151 165 raise Exception('delivery key is invalid: ' + self.key) … … 157 171 self.source_context_type = source_context_type 158 172 self.policy_deliveries = policy_deliveries 173 174 def __eq__(self, other): 175 return type(self) is type(other) and self.__dict__ == other.__dict__ 159 176 160 177 @classmethod -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/w3c-import.log
r253683 r263621 17 17 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/format_spec_src_json.py 18 18 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/generate.py 19 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/spec.src.json 19 20 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/spec_validator.py 20 21 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/tools/util.py -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/security-features/w3c-import.log
r245004 r263621 16 16 List of files: 17 17 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/README.md 18 /LayoutTests/imported/w3c/web-platform-tests/common/security-features/types.md -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/stringifiers.js
r179439 r263621 1 // Tests <http://heycam.github.io/webidl/#es-stringifier>. 1 /** 2 * Runs tests for <http://heycam.github.io/webidl/#es-stringifier>. 3 * @param {Object} aObject - object to test 4 * @param {string} aAttribute - IDL attribute name that is annotated with `stringifier` 5 * @param {boolean} aIsUnforgeable - whether the IDL attribute is `[Unforgeable]` 6 */ 2 7 function test_stringifier_attribute(aObject, aAttribute, aIsUnforgeable) { 3 8 // Step 1. 4 9 test(function() { 5 10 [null, undefined].forEach(function(v) { 6 assert_throws (new TypeError(), function() {11 assert_throws_js(TypeError, function() { 7 12 aObject.toString.call(v); 8 13 }); … … 16 21 assert_false("Window" in window && aObject instanceof window.Window); 17 22 [{}, window].forEach(function(v) { 18 assert_throws (new TypeError(), function() {23 assert_throws_js(TypeError, function() { 19 24 aObject.toString.call(v) 20 25 }); -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/subset-tests-by-key.js
r239693 r263621 1 // Only test a subset of tests with ?include=Foo or ?exclude=Foo in the URL.2 // Can be used together with <meta name="variant" content="...">3 // Sample usage:4 // for (const test of tests) {5 // subsetTestByKey("Foo", async_test, test.fn, test.name);6 // }7 1 (function() { 8 2 var subTestKeyPattern = null; … … 49 43 } 50 44 } 45 /** 46 * Check if `key` is in the subset specified in the URL. 47 * @param {string} key 48 * @returns {boolean} 49 */ 51 50 function shouldRunSubTest(key) { 52 51 if (key && subTestKeyPattern) { … … 59 58 return true; 60 59 } 61 function subsetTestByKey(key, testFunc, ...args) { 60 /** 61 * Only test a subset of tests with `?include=Foo` or `?exclude=Foo` in the URL. 62 * Can be used together with `<meta name="variant" content="...">` 63 * Sample usage: 64 * for (const test of tests) { 65 * subsetTestByKey("Foo", async_test, test.fn, test.name); 66 * } 67 */ 68 function subsetTestByKey(key, testFunc, ...args) { 62 69 if (collectKeys) { 63 70 if (collectCounts && key in keys) { -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/subset-tests.js
r232903 r263621 1 // Only test a subset of tests with, e.g., ?1-10 in the URL.2 // Can be used together with <meta name="variant" content="...">3 // Sample usage:4 // for (const test of tests) {5 // subsetTest(async_test, test.fn, test.name);6 // }7 1 (function() { 8 2 var subTestStart = 0; … … 38 32 } 39 33 } 34 /** 35 * Check if `currentSubTest` is in the subset specified in the URL. 36 * @param {number} currentSubTest 37 * @returns {boolean} 38 */ 40 39 function shouldRunSubTest(currentSubTest) { 41 40 return currentSubTest >= subTestStart && currentSubTest <= subTestEnd; 42 41 } 43 42 var currentSubTest = 0; 43 /** 44 * Only test a subset of tests with, e.g., `?1-10` in the URL. 45 * Can be used together with `<meta name="variant" content="...">` 46 * Sample usage: 47 * for (const test of tests) { 48 * subsetTest(async_test, test.fn, test.name); 49 * } 50 */ 44 51 function subsetTest(testFunc, ...args) { 45 52 currentSubTest++; -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/test-setting-immutable-prototype.js
r214135 r263621 1 1 self.testSettingImmutablePrototypeToNewValueOnly = 2 (prefix, target, newValue, newValueString, { isSameOriginDomain }) => { 2 (prefix, target, newValue, newValueString, { isSameOriginDomain }, 3 targetGlobal = window) => { 3 4 test(() => { 4 assert_throws (newTypeError, () => {5 assert_throws_js(TypeError, () => { 5 6 Object.setPrototypeOf(target, newValue); 6 7 }); … … 10 11 let dunderProtoErrorName = "\"SecurityError\" DOMException"; 11 12 if (isSameOriginDomain) { 12 dunderProtoError = new TypeError(); 13 // We're going to end up calling the __proto__ setter, which will 14 // enter the Realm of targetGlobal before throwing. 15 dunderProtoError = targetGlobal.TypeError; 13 16 dunderProtoErrorName = "TypeError"; 14 17 } 15 18 16 19 test(() => { 17 assert_throws(dunderProtoError,function() {20 const func = function() { 18 21 target.__proto__ = newValue; 19 }); 22 }; 23 if (isSameOriginDomain) { 24 assert_throws_js(dunderProtoError, func); 25 } else { 26 assert_throws_dom(dunderProtoError, func); 27 } 20 28 }, `${prefix}: setting the prototype to ${newValueString} via __proto__ should throw a ${dunderProtoErrorName}`); 21 29 … … 26 34 27 35 self.testSettingImmutablePrototype = 28 (prefix, target, originalValue, { isSameOriginDomain }, newValue = {}, newValueString = "an empty object") => { 29 testSettingImmutablePrototypeToNewValueOnly(prefix, target, newValue, newValueString, { isSameOriginDomain }); 36 (prefix, target, originalValue, { isSameOriginDomain }, targetGlobal = window) => { 37 const newValue = {}; 38 const newValueString = "an empty object"; 39 testSettingImmutablePrototypeToNewValueOnly(prefix, target, newValue, newValueString, { isSameOriginDomain }, targetGlobal); 30 40 31 41 const originalValueString = originalValue === null ? "null" : "its original value"; … … 45 55 } else { 46 56 test(() => { 47 assert_throws ("SecurityError", function() {57 assert_throws_dom("SecurityError", function() { 48 58 target.__proto__ = newValue; 49 59 }); -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/utils.js
r179439 r263621 1 /** 2 * Create an absolute URL from `options` and defaulting unspecified properties to `window.location`. 3 * @param {Object} options - a `Location`-like object 4 * @param {string} options.hostname 5 * @param {string} options.subdomain - prepend subdomain to the hostname 6 * @param {string} options.port 7 * @param {string} options.path 8 * @param {string} options.query 9 * @param {string} options.hash 10 * @returns {string} 11 */ 1 12 function make_absolute_url(options) { 2 13 var loc = window.location; … … 42 53 } 43 54 55 /** @private */ 44 56 function get(obj, name, default_val) { 45 57 if (obj.hasOwnProperty(name)) { … … 49 61 } 50 62 63 /** 64 * Generate a new UUID. 65 * @returns {string} 66 */ 51 67 function token() { 52 68 var uuid = [to_hex(rand_int(32), 8), … … 58 74 } 59 75 76 /** @private */ 60 77 function rand_int(bits) { 61 78 if (bits < 1 || bits > 53) { … … 72 89 } 73 90 91 /** @private */ 74 92 function to_hex(x, length) { 75 93 var rv = x.toString(16); -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/w3c-import.log
r253683 r263621 39 39 /LayoutTests/imported/w3c/web-platform-tests/common/reftest-wait.js 40 40 /LayoutTests/imported/w3c/web-platform-tests/common/reftest-wait.js.headers 41 /LayoutTests/imported/w3c/web-platform-tests/common/rendering-utils.js 42 /LayoutTests/imported/w3c/web-platform-tests/common/sab.js 41 43 /LayoutTests/imported/w3c/web-platform-tests/common/slow.py 42 44 /LayoutTests/imported/w3c/web-platform-tests/common/stringifiers.js -
trunk/LayoutTests/imported/w3c/web-platform-tests/common/worklet-reftest.js
r245004 r263621 1 // Imports code into a worklet. E.g. 2 // 3 // importWorklet(CSS.paintWorklet, {url: 'script.js'}); 4 // importWorklet(CSS.paintWorklet, '/* javascript string */'); 1 /** 2 * Imports code into a worklet. E.g. 3 * 4 * importWorklet(CSS.paintWorklet, {url: 'script.js'}); 5 * importWorklet(CSS.paintWorklet, '(javascript string)'); 6 * 7 * @param {Worklet} worklet 8 * @param {(Object|string)} code 9 */ 5 10 function importWorklet(worklet, code) { 6 11 let url; … … 15 20 } 16 21 22 /** @private */ 17 23 async function animationFrames(frames) { 18 24 for (let i = 0; i < frames; i++) … … 20 26 } 21 27 28 /** @private */ 22 29 async function workletPainted() { 23 30 await animationFrames(2); 24 31 } 25 32 26 // To make sure that we take the snapshot at the right time, we do double 27 // requestAnimationFrame. In the second frame, we take a screenshot, that makes 28 // sure that we already have a full frame. 33 /** 34 * To make sure that we take the snapshot at the right time, we do double 35 * requestAnimationFrame. In the second frame, we take a screenshot, that makes 36 * sure that we already have a full frame. 37 * 38 * @param {Worklet} worklet 39 * @param {(Object|string)} code 40 */ 29 41 async function importWorkletAndTerminateTestAfterAsyncPaint(worklet, code) { 30 42 if (typeof worklet === 'undefined') { -
trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub-expected.txt
r259900 r263621 4 4 FAIL Same-origin-domain prerequisite check: the original prototype is accessible assert_not_equals: got disallowed value null 5 5 PASS Same-origin-domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError 6 FAIL Same-origin-domain: setting the prototype to an empty object via __proto__ should throw a TypeError assert_throws : function "function () {6 FAIL Same-origin-domain: setting the prototype to an empty object via __proto__ should throw a TypeError assert_throws_js: function "function () { 7 7 target.__proto__ = newValue; 8 }" threw object "SecurityError: Blocked a frame with origin "http://localhost:8800" from accessing a cross-origin frame. Protocols, domains, and ports must match." ("SecurityError") expected object "TypeError" ("TypeError") 8 }" threw object "SecurityError: Blocked a frame with origin "http://localhost:8800" from accessing a cross-origin frame. Protocols, domains, and ports must match." ("SecurityError") expected instance of function "function TypeError() { 9 [native code] 10 }" ("TypeError") 9 11 PASS Same-origin-domain: setting the prototype to an empty object via Reflect.setPrototypeOf should return false 10 12 PASS Same-origin-domain: the prototype must still be null -
trunk/LayoutTests/imported/w3c/web-platform-tests/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-same-origin-domain.sub-expected.txt
r259900 r263621 4 4 FAIL Same-origin-domain prerequisite check: the original prototype is accessible assert_not_equals: got disallowed value null 5 5 PASS Same-origin-domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError 6 FAIL Same-origin-domain: setting the prototype to an empty object via __proto__ should throw a TypeError assert_throws : function "function () {6 FAIL Same-origin-domain: setting the prototype to an empty object via __proto__ should throw a TypeError assert_throws_js: function "function () { 7 7 target.__proto__ = newValue; 8 }" threw object "SecurityError: Blocked a frame with origin "http://localhost:8800" from accessing a cross-origin frame. Protocols, domains, and ports must match." ("SecurityError") expected object "TypeError" ("TypeError") 8 }" threw object "SecurityError: Blocked a frame with origin "http://localhost:8800" from accessing a cross-origin frame. Protocols, domains, and ports must match." ("SecurityError") expected instance of function "function TypeError() { 9 [native code] 10 }" ("TypeError") 9 11 PASS Same-origin-domain: setting the prototype to an empty object via Reflect.setPrototypeOf should return false 10 12 PASS Same-origin-domain: the prototype must still be null
Note: See TracChangeset
for help on using the changeset viewer.